diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/SystemAgent/SmmAccess | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SmmAccess')
14 files changed, 1674 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.cif b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.cif new file mode 100644 index 0000000..b754f8b --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.cif @@ -0,0 +1,13 @@ +<component> + name = "SmmAccess" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\SystemAgent\SmmAccess\Dxe" + RefName = "SmmAccess" +[files] +"SmmAccess.sdl" +"SmmAccess.mak" +"SmmAccessDriver.c" +"SmmAccessDriver.h" +"SmmAccess.dxs" +"SmmAccess.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.dxs b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.dxs new file mode 100644 index 0000000..30e8eb6 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.dxs @@ -0,0 +1,40 @@ +/** @file + Dependency expression file for Smm Access Driver. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" +#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo) +#endif + +DEPENDENCY_START + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.inf b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.inf new file mode 100644 index 0000000..f19577b --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.inf @@ -0,0 +1,82 @@ +## @file +# Component description file for the SmmAccess module +# {1323C7F8-DAD5-4126-A54B-7A05FBF4151} +# +#@copyright +# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = SmmAccess +FILE_GUID = 1323C7F8-DAD5-4126-A54B-7A05FBF41515 +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + SmmAccessDriver.h + SmmAccessDriver.c +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueDxeDriverEntryPoint.c + +[includes.common] + . + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library + +[libraries.common] + EdkFrameworkGuidLib + EdkFrameworkProtocolLib + EfiProtocolLib + EfiCommonLib + EfiScriptLib + EdkIIGlueBaseLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueDxeReportStatusCodeLib + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueDxeServicesTableLib + EdkIIGlueDxeHobLib + EdkIIGlueDxeMemoryAllocationLib + EdkProtocolLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = SmmAccess.dxs + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=SmmAccessDriverEntryPoint \ + -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_LIB__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_HOB_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.mak b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.mak new file mode 100644 index 0000000..59d1450 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.mak @@ -0,0 +1,63 @@ +#--------------------------------------------------------------------------- +# Create SmmAccess Driver +#--------------------------------------------------------------------------- +EDK : SmmAccess + +SmmAccess : $(BUILD_DIR)\SmmAccess.mak SmmAccessBin + +$(BUILD_DIR)\SmmAccess.mak : $(SmmAccess_DIR)\$(@B).cif $(SmmAccess_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(SmmAccess_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +SmmAccess_INCLUDES = \ + $(EdkIIGlueLib_INCLUDES)\ + $(EDK_INCLUDES)\ + $(INTEL_MCH_INCLUDES) + +SmmAccess_DEFINES = $(MY_DEFINES)\ + /D "__EDKII_GLUE_MODULE_ENTRY_POINT__=SmmAccessDriverEntryPoint" \ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_LIB__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_DXE_HOB_LIB__\ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + +SmmAccess_LIB_LINKS =\ + $(EDKFRAMEWORKGUIDLIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EFIPROTOCOLLIB)\ + $(EFICOMMONLIB)\ + $(EFISCRIPTLIB)\ + $(EdkIIGlueBaseLib_LIB)\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeHobLib_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EDKPROTOCOLLIB)\ + +SmmAccessBin: $(SmmAccess_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\SmmAccess.mak all \ + "MY_INCLUDES=$(SmmAccess_INCLUDES)" \ + "MY_DEFINES=$(SmmAccess_DEFINES)"\ + GUID=1323C7F8-DAD5-4126-A54B-7A05FBF41515\ + ENTRY_POINT=_ModuleEntryPoint\ + TYPE=BS_DRIVER \ + EDKIIModule=DXEDRIVER\ + DEPEX1=$(SmmAccess_DIR)\SmmAccess.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \ + COMPRESS=1 diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.sdl b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.sdl new file mode 100644 index 0000000..89077d9 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccess.sdl @@ -0,0 +1,30 @@ +TOKEN + Name = "SmmAccess_SUPPORT" + Value = "1" + Help = "Main switch to enable SmmAccess support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes + Token = "SMM_SUPPORT" "=" "1" +End + +PATH + Name = "SmmAccess_DIR" +End + +MODULE + Help = "Includes SmmAccess to Project" + File = "SmmAccess.mak" +End + +ELINK + Name = "SmmAccess" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\SmmAccess.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End + diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c new file mode 100644 index 0000000..f91c170 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.c @@ -0,0 +1,457 @@ +/** @file + This is the driver that publishes the SMM Access Protocol + instance for System Agent. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "SmmAccessDriver.h" + +static SMM_ACCESS_PRIVATE_DATA mSmmAccess; + +EFI_DRIVER_ENTRY_POINT (SmmAccessDriverEntryPoint) + +/** + This is the standard EFI driver point that + installs an SMM Access Protocol + + @param[in] ImageHandle - Handle for the image of this driver + @param[in] SystemTable - Pointer to the EFI System Table + + @retval EFI_SUCCESS - Protocol was installed successfully + @exception EFI_UNSUPPORTED - Protocol was not installed + @retval EFI_NOT_FOUND - Protocol can't be found. + @retval EFI_OUT_OF_RESOURCES - Protocol does not have enough resources to initialize the driver. +**/ +EFI_STATUS +SmmAccessDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINTN Index; + EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock; + EFI_PEI_HOB_POINTERS *Hob; + + /// + /// --cr-- INITIALIZE_SCRIPT (ImageHandle, SystemTable); + /// + /// Initialize Global variables + /// + ZeroMem (&mSmmAccess, sizeof (mSmmAccess)); + + Status = gBS->LocateProtocol ( + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + (VOID **) &PciRootBridgeIo + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Could not locate PCI Root Bridge IO Protocol\n")); + return EFI_NOT_FOUND; + } + + mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE; + mSmmAccess.Handle = NULL; + mSmmAccess.PciRootBridgeIo = PciRootBridgeIo; + + /// + /// Get Hob list + /// + Hob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserve); + if (Hob == NULL) { + DEBUG ((EFI_D_ERROR, "SmramMemoryReserve HOB not found\n")); + return EFI_NOT_FOUND; + } + + DescriptorBlock = (VOID *) ((UINT8 *) Hob + sizeof (EFI_HOB_GUID_TYPE)); + + /// + /// Alloc space for mSmmAccess.SmramDesc + /// + mSmmAccess.SmramDesc = AllocateZeroPool ((DescriptorBlock->NumberOfSmmReservedRegions) * sizeof (EFI_SMRAM_DESCRIPTOR)); + if (mSmmAccess.SmramDesc == NULL) { + DEBUG ((EFI_D_ERROR, "Alloc mSmmAccess.SmramDesc fail.\n")); + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((EFI_D_INFO, "Alloc mSmmAccess.SmramDesc success.\n")); + + /// + /// Use the HOB to publish SMRAM capabilities + /// + for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) { + mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart; + mSmmAccess.SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart; + mSmmAccess.SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize; + mSmmAccess.SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState; + } + + mSmmAccess.NumberRegions = Index; + mSmmAccess.SmmAccess.Open = Open; + mSmmAccess.SmmAccess.Close = Close; + mSmmAccess.SmmAccess.Lock = Lock; + mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities; + mSmmAccess.SmmAccess.LockState = FALSE; + mSmmAccess.SmmAccess.OpenState = FALSE; + + /// + /// Install our protocol interfaces on the device's handle + /// + Status = gBS->InstallMultipleProtocolInterfaces ( + &mSmmAccess.Handle, + &gEfiSmmAccessProtocolGuid, + &mSmmAccess.SmmAccess, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "InstallMultipleProtocolInterfaces returned %r\n", Status)); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "open" a region of SMRAM. The + region could be legacy ABSEG, HSEG, or TSEG near top of physical memory. + The use of "open" means that the memory is visible from all boot-service + and SMM agents. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Open. + + @retval EFI_SUCCESS - The region was successfully opened. + @retval EFI_DEVICE_ERROR - The region could not be opened because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Open ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ) +{ + EFI_STATUS Status; + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + UINT64 Address; + UINT8 SmramControl; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) { + /// + /// Cannot open a "locked" region + /// + DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n")); + + return EFI_DEVICE_ERROR; + } + /// + /// BEGIN CHIPSET SPECIFIC CODE + /// + /// + /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit) + /// + Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC); + + Status = SmmAccess->PciRootBridgeIo->Pci.Read ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status)); + return Status; + } + /// + /// Is SMRAM locked? + /// + if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) { + /// + /// Cannot Open a locked region + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + /// + /// Open SMRAM region + /// + SmramControl |= B_SA_SMRAMC_D_OPEN_MASK; + SmramControl &= ~(B_SA_SMRAMC_D_CLS_MASK); + + Status = SmmAccess->PciRootBridgeIo->Pci.Write ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status)); + return Status; + } + /// + /// END CHIPSET SPECIFIC CODE + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED); + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN; + SmmAccess->SmmAccess.OpenState = TRUE; + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "close" a region of SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "close" means that the memory is only visible from SMM agents, + not from BS or RT code. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Close. + + @retval EFI_SUCCESS - The region was successfully closed. + @retval EFI_DEVICE_ERROR - The region could not be closed because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Close ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ) +{ + EFI_STATUS Status; + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + UINT64 Address; + BOOLEAN OpenState; + UINT8 Index; + UINT8 SmramControl; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) { + /// + /// Cannot close a "locked" region + /// + DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + + if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) { + return EFI_DEVICE_ERROR; + } + /// + /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit) + /// + Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC); + + Status = SmmAccess->PciRootBridgeIo->Pci.Read ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status)); + return Status; + } + /// + /// Is SMRAM locked? + /// + if ((SmramControl & B_SA_SMRAMC_D_LCK_MASK) != 0) { + /// + /// Cannot Close a locked region + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + /// + /// Close SMRAM region + /// + SmramControl &= ~(B_SA_SMRAMC_D_OPEN_MASK); + + Status = SmmAccess->PciRootBridgeIo->Pci.Write ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status)); + return Status; + } + /// + /// END CHIPSET SPECIFIC CODE + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN; + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED); + + /// + /// Find out if any regions are still open + /// + OpenState = FALSE; + for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) { + if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) { + OpenState = TRUE; + } + } + + SmmAccess->SmmAccess.OpenState = OpenState; + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "lock" SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "lock" means that the memory can no longer be opened + to BS state.. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Lock. + + @retval EFI_SUCCESS - The region was successfully locked. + @retval EFI_DEVICE_ERROR - The region could not be locked because at least + one range is still open. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Lock ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ) +{ + EFI_STATUS Status; + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + UINT64 Address; + UINT8 SmramControl; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmmAccess.OpenState) { + DEBUG ((EFI_D_WARN, "Cannot lock SMRAM when SMRAM regions are still open\n")); + return EFI_DEVICE_ERROR; + } + + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + SmmAccess->SmmAccess.LockState = TRUE; + + /// + /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit) + /// + Address = EFI_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC); + + Status = SmmAccess->PciRootBridgeIo->Pci.Read ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Read returned %r\n", Status)); + return Status; + } + /// + /// Lock the SMRAM + /// + SmramControl |= B_SA_SMRAMC_D_LCK_MASK; + + Status = SmmAccess->PciRootBridgeIo->Pci.Write ( + SmmAccess->PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &SmramControl + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmmAccess->PciRootBridgeIo->Pci.Write returned %r\n", Status)); + return Status; + } + /// + /// END CHIPSET SPECIFIC CODE + /// + return EFI_SUCCESS; +} + +/** + This routine services a user request to discover the SMRAM + capabilities of this platform. This will report the possible + ranges that are possible for SMRAM access, based upon the + memory controller capabilities. + + @param[in] This - Pointer to the SMRAM Access Interface. + @param[in] SmramMapSize - Pointer to the variable containing size of the + buffer to contain the description information. + @param[in] SmramMap - Buffer containing the data describing the Smram + region descriptors. + + @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer. + @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer. +**/ +EFI_STATUS +EFIAPI +GetCapabilities ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +{ + EFI_STATUS Status; + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + UINTN NecessaryBufferSize; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + + NecessaryBufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR); + + if (*SmramMapSize < NecessaryBufferSize) { + DEBUG ((EFI_D_WARN, "SMRAM Map Buffer too small\n")); + Status = EFI_BUFFER_TOO_SMALL; + } else { + CopyMem (SmramMap, SmmAccess->SmramDesc, NecessaryBufferSize); + Status = EFI_SUCCESS; + } + + *SmramMapSize = NecessaryBufferSize; + + return Status; +} diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h new file mode 100644 index 0000000..4d98f27 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Dxe/SmmAccessDriver.h @@ -0,0 +1,178 @@ +/** @file + Header file for SMM Access Driver. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _SMM_ACCESS_DRIVER_H_ +#define _SMM_ACCESS_DRIVER_H_ + +#include "EdkIIGlueDxe.h" +#include "pci22.h" +#include "EdkIIGlueHobLib.h" +#include "EfiScriptLib.h" +#include "SaAccess.h" + +/// +/// Driver Consumed Protocol Prototypes +/// +#include EFI_PROTOCOL_CONSUMER (PciRootBridgeIo) + +/// +/// Driver private data +/// +#include EFI_GUID_DEFINITION (SmramMemoryReserve) +#include EFI_GUID_DEFINITION (Hob) +#include EFI_PROTOCOL_DEFINITION (SmmAccess) + +#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('4', '5', 's', 'a') + +/// +/// Private data +/// +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SMM_ACCESS_PROTOCOL SmmAccess; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + /// + /// Local Data for SMM Access interface goes here + /// + UINTN NumberRegions; + EFI_SMRAM_DESCRIPTOR *SmramDesc; +} SMM_ACCESS_PRIVATE_DATA; + +#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + SMM_ACCESS_PRIVATE_DATA, \ + SmmAccess, \ + SMM_ACCESS_PRIVATE_DATA_SIGNATURE \ + ) + +/// +/// Prototypes +/// Driver model protocol interface +/// +/** + This is the standard EFI driver point that + installs an SMM Access Protocol + + @param[in] ImageHandle - Handle for the image of this driver + @param[in] SystemTable - Pointer to the EFI System Table + + @retval EFI_SUCCESS - Protocol was installed successfully + @exception EFI_UNSUPPORTED - Protocol was not installed +**/ +EFI_STATUS +SmmAccessDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +/** + This routine accepts a request to "open" a region of SMRAM. The + region could be legacy ABSEG, HSEG, or TSEG near top of physical memory. + The use of "open" means that the memory is visible from all boot-service + and SMM agents. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Open. + + @retval EFI_SUCCESS - The region was successfully opened. + @retval EFI_DEVICE_ERROR - The region could not be opened because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Open ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine accepts a request to "close" a region of SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "close" means that the memory is only visible from SMM agents, + not from BS or RT code. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Close. + + @retval EFI_SUCCESS - The region was successfully closed. + @retval EFI_DEVICE_ERROR - The region could not be closed because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Close ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine accepts a request to "lock" SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "lock" means that the memory can no longer be opened + to BS state.. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Lock. + + @retval EFI_SUCCESS - The region was successfully locked. + @retval EFI_DEVICE_ERROR - The region could not be locked because at least + one range is still open. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Lock ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine services a user request to discover the SMRAM + capabilities of this platform. This will report the possible + ranges that are possible for SMRAM access, based upon the + memory controller capabilities. + + @param[in] This - Pointer to the SMRAM Access Interface. + @param[in] SmramMapSize - Pointer to the variable containing size of the + buffer to contain the description information. + @param[in] SmramMap - Buffer containing the data describing the Smram + region descriptors. + + @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer. + @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer. +**/ +EFI_STATUS +EFIAPI +GetCapabilities ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +; + +#endif diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccess.inf b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccess.inf new file mode 100644 index 0000000..99b2a6d --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccess.inf @@ -0,0 +1,91 @@ +## @file +# Component description file for the SmmAccess module +# +#@copyright +# Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# +## + +[defines] +BASE_NAME = SmmAccess +FILE_GUID = 6ECFCE51-5724-450c-A38A-58553E954422 +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + SmmAccessPeim.h + SmmAccessPeim.c + +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + +[includes.common] + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Pei/Include + $(EFI_SOURCE)/$(PROJECT_SA_ROOT) + $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include + $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include + $(CLIENT_COMMON_ECP_SOURCE) + +# +# Edk II Glue Library, some hearder are included by R9 header so have to include +# + + $(EFI_SOURCE) + $(EFI_SOURCE)/Framework + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + +[libraries.common] + EdkIIGlueBaseLib + EdkIIGlueBaseMemoryLib + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGluePeiHobLib + EdkIIGlueBasePciLibPciExpress + EdkIIGluePeiMemoryAllocationLib + IntelSaSampleCodePpiLib + +[nmake.common] + IMAGE_ENTRY_POINT=_ModuleEntryPoint + DPX_SOURCE=SmmAccessPeim.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=SmmAccessPeimEntryPoint + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_PEI_HOB_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + -D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_PEI_SERVICES_LIB__ diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.c b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.c new file mode 100644 index 0000000..fc2ab44 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.c @@ -0,0 +1,407 @@ +/** @file + This is the driver that publishes the SMM Access Ppi + instance. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include "SmmAccessPeim.h" +#include "CpuIA32.h" +#endif + +/** + This is the standard PEIM entry point that + installs an SMM Access PPI + + @param[in] FfsHeader - FfsHeader. + @param[in] PeiServices - General purpose services available to every PEIM. + + @retval EFI_SUCCESS - Protocol successfully started and installed. + @exception EFI_UNSUPPORTED - Protocol can't be started. + @retval EFI_NOT_FOUND - Protocol can't be found. + @retval EFI_OUT_OF_RESOURCES - Protocol does not have enough resources to initialize the driver. +**/ +EFI_STATUS +EFIAPI +SmmAccessPeimEntryPoint ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINT32 PciVidDid; + UINTN Index; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock; + SMM_ACCESS_PRIVATE_DATA *SmmAccessPrivate; + VOID *HobList; + EFI_BOOT_MODE BootMode; + + Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode); + if (EFI_ERROR (Status)) { + /// + /// If not in S3 boot path. do nothing + /// + return EFI_SUCCESS; + } + + if (BootMode != BOOT_ON_S3_RESUME) { + return EFI_SUCCESS; + } + /// + /// Initialize private data + /// + SmmAccessPrivate = AllocateZeroPool (sizeof (*SmmAccessPrivate)); + PpiList = AllocateZeroPool (sizeof (*PpiList)); + + /// + /// Check if the chipset is supported + /// by this driver. Read the PCI Configuration Header for this device. + /// + PciVidDid = PciRead32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, 0)); + + SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE; + SmmAccessPrivate->Handle = NULL; + + /// + /// Get Hob list + /// + HobList = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserve); + if (HobList == NULL) { + DEBUG ((EFI_D_ERROR, "SmramMemoryReserve HOB not found\n")); + return EFI_NOT_FOUND; + } + + DescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) ((UINT8 *) HobList + sizeof (EFI_HOB_GUID_TYPE)); + + /// + /// Alloc space for SmmAccessPrivate->SmramDesc + /// + SmmAccessPrivate->SmramDesc = AllocateZeroPool ((DescriptorBlock->NumberOfSmmReservedRegions) * sizeof (EFI_SMRAM_DESCRIPTOR)); + if (SmmAccessPrivate->SmramDesc == NULL) { + DEBUG ((EFI_D_ERROR, "Alloc SmmAccessPrivate->SmramDesc fail.\n")); + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((EFI_D_INFO, "Alloc SmmAccessPrivate->SmramDesc success.\n")); + + /// + /// use the hob to publish SMRAM capabilities + /// + for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) { + SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart; + SmmAccessPrivate->SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart; + SmmAccessPrivate->SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize; + SmmAccessPrivate->SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState; + } + + SmmAccessPrivate->NumberRegions = Index; + SmmAccessPrivate->SmmAccess.Open = Open; + SmmAccessPrivate->SmmAccess.Close = Close; + SmmAccessPrivate->SmmAccess.Lock = Lock; + SmmAccessPrivate->SmmAccess.GetCapabilities = GetCapabilities; + SmmAccessPrivate->SmmAccess.LockState = FALSE; + SmmAccessPrivate->SmmAccess.OpenState = FALSE; + + /// + /// Install PPI + /// + PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PpiList->Guid = &gPeiSmmAccessPpiGuid; + PpiList->Ppi = &SmmAccessPrivate->SmmAccess; + + Status = PeiServicesInstallPpi (PpiList); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "open" a region of SMRAM. The + region could be legacy ABSEG, HSEG, or TSEG near top of physical memory. + The use of "open" means that the memory is visible from all PEIM + and SMM agents. + + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Open. + @param[in] PeiServices - General purpose services available to every PEIM. + + @retval EFI_SUCCESS - The region was successfully opened. + @retval EFI_DEVICE_ERROR - The region could not be opened because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Open ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + SMRAM Smram; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) { + /// + /// Cannot open a "locked" region + /// + DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n")); + + return EFI_DEVICE_ERROR; + } + /// + /// BEGIN CHIPSET SPECIFIC CODE + /// + /// + /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit) + /// + Smram = PciRead32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC)); + + /// + /// Is SMRAM locked? + /// + if (Smram & B_SA_SMRAMC_D_LCK_MASK) { + /// + /// Cannot Open a locked region + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n")); + + return EFI_DEVICE_ERROR; + } + /// + /// Open SMRAM region + /// + Smram |= B_SA_SMRAMC_D_OPEN_MASK; + Smram &= ~(B_SA_SMRAMC_D_CLS_MASK); + + /// + /// Write the SMRAMC register + /// + PciWrite32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), Smram); + + /// + /// END CHIPSET SPECIFIC CODE + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED); + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN; + SmmAccess->SmmAccess.OpenState = TRUE; + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "close" a region of SMRAM. This is valid for + compatible SMRAM region. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Close. + + @retval EFI_SUCCESS - The region was successfully closed. + @retval EFI_DEVICE_ERROR - The region could not be closed because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Close ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + BOOLEAN OpenState; + UINT8 Index; + SMRAM Smram; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) { + /// + /// Cannot close a "locked" region + /// + DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n")); + + return EFI_DEVICE_ERROR; + } + + if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) { + return EFI_DEVICE_ERROR; + } + /// + /// SMRAM register is PCI 0:0:0:88, SMRAMC (8 bit) + /// + Smram = PciRead32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC)); + + /// + /// Is SMRAM locked? + /// + if ((Smram & B_SA_SMRAMC_D_LCK_MASK) != 0) { + /// + /// Cannot Close a locked region + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n")); + return EFI_DEVICE_ERROR; + } + /// + /// Close SMRAM region + /// + Smram &= ~(B_SA_SMRAMC_D_OPEN_MASK); + + /// + /// Write the SAD_SMRAM register + /// + PciWrite32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), Smram); + + /// + /// END CHIPSET SPECIFIC CODE + /// + SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN; + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED); + + /// + /// Find out if any regions are still open + /// + OpenState = FALSE; + for (Index = 0; Index < SmmAccess->NumberRegions; Index++) { + if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) { + OpenState = TRUE; + } + } + + SmmAccess->SmmAccess.OpenState = OpenState; + return EFI_SUCCESS; +} + +/** + This routine accepts a request to "lock" SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "lock" means that the memory can no longer be opened + to PEIM. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Lock. + + @retval EFI_SUCCESS - The region was successfully locked. + @retval EFI_DEVICE_ERROR - The region could not be locked because at least + one range is still open. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Lock ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +{ + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + SMRAM Smram; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + if (DescriptorIndex >= SmmAccess->NumberRegions) { + DEBUG ((EFI_D_WARN, "SMRAM region out of range\n")); + + return EFI_INVALID_PARAMETER; + } else if (SmmAccess->SmmAccess.OpenState) { + DEBUG ((EFI_D_WARN, "Cannot lock SMRAM when SMRAM regions are still open\n")); + + return EFI_DEVICE_ERROR; + } + + SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED; + SmmAccess->SmmAccess.LockState = TRUE; + + /// + /// Read the SAD_SMRAM register + /// + Smram = PciRead32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC)); + + /// + /// Lock the chipset + /// + Smram |= B_SA_SMRAMC_D_LCK_MASK; + + /// + /// Write the SAD_SMRAM register + /// + PciWrite32 (PCI_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), Smram); + + /// + /// END CHIPSET SPECIFIC CODE + /// + return EFI_SUCCESS; +} + +/** + This routine services a user request to discover the SMRAM + capabilities of this platform. This will report the possible + ranges that are possible for SMRAM access, based upon the + memory controller capabilities. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMRAM Access Interface. + @param[in] SmramMapSize - Pointer to the variable containing size of the + buffer to contain the description information. + @param[in] SmramMap - Buffer containing the data describing the Smram + region descriptors. + + @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer. + @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer. +**/ +EFI_STATUS +EFIAPI +GetCapabilities ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +{ + EFI_STATUS Status; + SMM_ACCESS_PRIVATE_DATA *SmmAccess; + UINTN NecessaryBufferSize; + + SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This); + NecessaryBufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR); + if (*SmramMapSize < NecessaryBufferSize) { + DEBUG ((EFI_D_WARN, "SMRAM Map Buffer too small\n")); + + Status = EFI_BUFFER_TOO_SMALL; + } else { + CopyMem (SmramMap, SmmAccess->SmramDesc, NecessaryBufferSize); + Status = EFI_SUCCESS; + } + + *SmramMapSize = NecessaryBufferSize; + return Status; +} diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.cif b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.cif new file mode 100644 index 0000000..d7f3ab1 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.cif @@ -0,0 +1,13 @@ +<component> + name = "SmmAccessPeim" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\SystemAgent\SmmAccess\Pei" + RefName = "SmmAccessPeim" +[files] +"SmmAccessPeim.sdl" +"SmmAccessPeim.mak" +"SmmAccessPeim.c" +"SmmAccessPeim.h" +"SmmAccessPeim.dxs" +"SmmAccess.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.dxs b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.dxs new file mode 100644 index 0000000..34e3dde --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.dxs @@ -0,0 +1,29 @@ +/** @file + Dependency expression file for Smm Access PEIM. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + + +#include "EfiDepex.h" +#include EFI_PPI_CONSUMER (MemoryDiscovered) +#include EFI_PPI_CONSUMER (BootMode) + +DEPENDENCY_START + PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID AND + PEI_MASTER_BOOT_MODE_PEIM_PPI +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.h b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.h new file mode 100644 index 0000000..c89cdaf --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.h @@ -0,0 +1,186 @@ +/** @file + Header file for SMM Access Driver. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#ifndef _SMM_ACCESS_DRIVER_H_ +#define _SMM_ACCESS_DRIVER_H_ + +#include "pci22.h" +#include "SaAccess.h" + +/// +/// Driver Consumed Protocol Prototypes +/// +/// +/// Driver Consumed GUID Prototypes +/// +#include EFI_GUID_DEFINITION (SmramMemoryReserve) + +/// +/// Driver produced protocol +/// +#include EFI_PPI_PRODUCER (SmmAccess) + +#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('4', '5', 's', 'a') + +/// +/// SMM configuration register +/// +typedef UINT32 SMRAM; /// System Management RAM Control +/// +/// Private data +/// +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + PEI_SMM_ACCESS_PPI SmmAccess; + /// + /// Local Data for SMM Access interface goes here + /// + UINTN NumberRegions; + EFI_SMRAM_DESCRIPTOR *SmramDesc; +} SMM_ACCESS_PRIVATE_DATA; + +#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \ + PEI_CR (a, \ + SMM_ACCESS_PRIVATE_DATA, \ + SmmAccess, \ + SMM_ACCESS_PRIVATE_DATA_SIGNATURE \ + ) + +/// +/// Prototypes +/// Driver model protocol interface +/// +/** + This is the standard PEIM entry point that + installs an SMM Access PPI + + @param[in] FfsHeader - Pointer to an alleged FFS file. + @param[in] PeiServices - General purpose services available to every PEIM. + + @retval EFI_STATUS - Protocol successfully started and installed +**/ +EFI_STATUS +EFIAPI +SmmAccessPeimEntryPoint ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; + +/** + This routine accepts a request to "open" a region of SMRAM. The + region could be legacy ABSEG, HSEG, or TSEG near top of physical memory. + The use of "open" means that the memory is visible from all boot-service + and SMM agents. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Open. + + @retval EFI_SUCCESS - The region was successfully opened. + @retval EFI_DEVICE_ERROR - The region could not be opened because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Open ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine accepts a request to "close" a region of SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "close" means that the memory is only visible from SMM agents, + not from BS or RT code. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Close. + + @retval EFI_SUCCESS - The region was successfully closed. + @retval EFI_DEVICE_ERROR - The region could not be closed because locked by + chipset. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Close ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine accepts a request to "lock" SMRAM. The + region could be legacy AB or TSEG near top of physical memory. + The use of "lock" means that the memory can no longer be opened + to BS state.. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMM Access Interface. + @param[in] DescriptorIndex - Region of SMRAM to Lock. + + @retval EFI_SUCCESS - The region was successfully locked. + @retval EFI_DEVICE_ERROR - The region could not be locked because at least + one range is still open. + @retval EFI_INVALID_PARAMETER - The descriptor index was out of bounds. +**/ +EFI_STATUS +EFIAPI +Lock ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN UINTN DescriptorIndex + ) +; + +/** + This routine services a user request to discover the SMRAM + capabilities of this platform. This will report the possible + ranges that are possible for SMRAM access, based upon the + memory controller capabilities. + + @param[in] PeiServices - General purpose services available to every PEIM. + @param[in] This - Pointer to the SMRAM Access Interface. + @param[in] SmramMapSize - Pointer to the variable containing size of the + buffer to contain the description information. + @param[in] SmramMap - Buffer containing the data describing the Smram + region descriptors. + + @retval EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer. + @retval EFI_SUCCESS - The user provided a sufficiently-sized buffer. +**/ +EFI_STATUS +EFIAPI +GetCapabilities ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_SMM_ACCESS_PPI *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ) +; + +#endif diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.mak b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.mak new file mode 100644 index 0000000..1cea8ff --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.mak @@ -0,0 +1,55 @@ +#--------------------------------------------------------------------------- +# Create SmmAccessPeim Driver +#--------------------------------------------------------------------------- +EDK : SmmAccessPeim +SmmAccessPeim : $(BUILD_DIR)\SmmAccessPeim.mak SmmAccessPeimBin + +$(BUILD_DIR)\SmmAccessPeim.mak : $(SmmAccessPeim_DIR)\$(@B).cif $(SmmAccessPeim_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(SmmAccessPeim_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +SmmAccessPeim_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_MCH_INCLUDES)\ + $(INTEL_CPU_INCLUDES)\ + +SmmAccessPeim_DEFINES = $(MY_DEFINES)\ + /DMDE_CPU_IA32\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=SmmAccessPeimEntryPoint"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_PEI_SERVICES_LIB__ \ + /D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + /D __EDKII_GLUE_PEI_HOB_LIB__\ + +SmmAccessPeim_LIB_LINKS =\ + $(EDKFRAMEWORKGUIDLIB)\ + $(EDKPPILIB)\ + $(EdkIIGlueBaseLibIA32_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\ + $(EdkIIGluePeiReportStatusCodeLib_LIB)\ + $(EdkIIGluePeiServicesLib_LIB)\ + $(EdkIIGluePeiMemoryAllocationLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EdkIIGlueBasePciExpressLib_LIB)\ + $(EdkIIGluePeiHobLib_LIB)\ + $(IntelSaSampleCodePpiLib_LIB)\ + +SmmAccessPeimBin: $(SmmAccessPeim_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\SmmAccessPeim.mak all\ + NAME=SmmAccessPeim\ + MAKEFILE=$(BUILD_DIR)\SmmAccessPeim.mak \ + GUID=6ECFCE51-5724-450c-A38A-58553E954422\ + "MY_INCLUDES=$(SmmAccessPeim_INCLUDES)"\ + "MY_DEFINES=$(SmmAccessPeim_DEFINES)"\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(SmmAccessPeim_DIR)\SmmAccessPeim.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \ + COMPRESS=0 diff --git a/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.sdl b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.sdl new file mode 100644 index 0000000..2217ebd --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/SmmAccess/Pei/SmmAccessPeim.sdl @@ -0,0 +1,30 @@ +TOKEN + Name = "SmmAccessPeim_SUPPORT" + Value = "1" + Help = "Main switch to enable SmmAccess support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes + Token = "SMM_SUPPORT" "=" "1" +End + +PATH + Name = "SmmAccessPeim_DIR" +End + +MODULE + Help = "Includes SmmAccess to Project" + File = "SmmAccessPeim.mak" +End + +ELINK + Name = "SmmAccessPeim" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\SmmAccessPeim.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent +End + |