+++ /dev/null
-/** @file\r
-This is the driver that publishes the SMM Access Protocol\r
-instance for the Tylersburg chipset.\r
-\r
-Copyright (c) 2013-2019 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "SmmAccessDriver.h"\r
-\r
-\r
-\r
-SMM_ACCESS_PRIVATE_DATA mSmmAccess;\r
-\r
-VOID\r
-SmmAccessOnBoot (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
-);\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-SmmAccessDriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Installs an SMM Access Protocol.\r
-\r
-Arguments:\r
-\r
- ImageHandle - Handle for the image of this driver.\r
- SystemTable - Pointer to the EFI System Table.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Protocol successfully started and installed.\r
- EFI_UNSUPPORTED - Protocol can't be started.\r
- EFI_NOT_FOUND - Protocol not found.\r
---*/\r
-{\r
-\r
- EFI_STATUS Status;\r
- EFI_EVENT BootEvent;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
- UINTN Index;\r
- EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
- EFI_HOB_GUID_TYPE *GuidHob;\r
-\r
-\r
- //\r
- // Initialize private data\r
- //\r
- ZeroMem (&mSmmAccess, sizeof (mSmmAccess));\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiPciRootBridgeIoProtocolGuid,\r
- NULL,\r
- (VOID **) &PciRootBridgeIo\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Build SMM related information\r
- //\r
- mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;\r
- mSmmAccess.Handle = NULL;\r
- mSmmAccess.PciRootBridgeIo = PciRootBridgeIo;\r
-\r
- //\r
- // Get Hob list\r
- //\r
- GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
- DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
- ASSERT (DescriptorBlock);\r
-\r
-\r
- //\r
- // Get CPU Max bus number\r
- //\r
- mSmmAccess.MaxBusNumber = PCI_BUS_NUMBER_QNC;\r
- for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {\r
- mSmmAccess.SocketPopulated[Index] = TRUE;\r
- }\r
-\r
- //\r
- // Use the hob to publish SMRAM capabilities\r
- //\r
- ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);\r
- for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
- mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;\r
- mSmmAccess.SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;\r
- mSmmAccess.SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;\r
- mSmmAccess.SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;\r
- DEBUG ((EFI_D_INFO, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index, mSmmAccess.SmramDesc[Index].CpuStart,\r
- mSmmAccess.SmramDesc[Index].PhysicalSize));\r
- }\r
-\r
- mSmmAccess.NumberRegions = Index;\r
- mSmmAccess.SmmAccess.Open = Open;\r
- mSmmAccess.SmmAccess.Close = Close;\r
- mSmmAccess.SmmAccess.Lock = Lock;\r
- mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities;\r
- mSmmAccess.SmmAccess.LockState = FALSE;\r
- mSmmAccess.SmmAccess.OpenState = FALSE;\r
- mSmmAccess.SMMRegionState = EFI_SMRAM_CLOSED;\r
-\r
- //\r
- // Install our protocol interfaces on the device's handle\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mSmmAccess.Handle,\r
- &gEfiSmmAccess2ProtocolGuid,\r
- &mSmmAccess.SmmAccess,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalStart)));\r
- DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize)));\r
-\r
- mSmmAccess.TsegSize = (UINT8)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize);\r
- //\r
- // T Seg setting done in QPI RC\r
- //\r
-\r
- //\r
- // Prior ReadyToBoot, lock CSEG\r
- //\r
- Status = EfiCreateEventReadyToBootEx(\r
- TPL_NOTIFY,\r
- SmmAccessOnBoot,\r
- NULL,\r
- &BootEvent );\r
- ASSERT (!EFI_ERROR (Status));\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-Open (\r
- IN EFI_SMM_ACCESS2_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine accepts a request to "open" a region of SMRAM. The\r
- region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
- The use of "open" means that the memory is visible from all boot-service\r
- and SMM agents.\r
-\r
-Arguments:\r
-\r
- This - Pointer to the SMM Access Interface.\r
- DescriptorIndex - Region of SMRAM to Open.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The region was successfully opened.\r
- EFI_DEVICE_ERROR - The region could not be opened because locked by\r
- chipset.\r
- EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
-\r
---*/\r
-{\r
- SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
-\r
- SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
- DEBUG ((EFI_D_ERROR, "Cannot open a locked SMRAM region\n"));\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Open TSEG\r
- //\r
- if (!QNCOpenSmramRegion ()) {\r
- mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- mSmmAccess.SMMRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
- SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED)));\r
- mSmmAccess.SMMRegionState |= EFI_SMRAM_OPEN;\r
- SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_OPEN);\r
- SmmAccess->SmmAccess.OpenState = TRUE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-Close (\r
- IN EFI_SMM_ACCESS2_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine accepts a request to "close" a region of SMRAM. This is valid for\r
- compatible SMRAM region.\r
-\r
-Arguments:\r
-\r
- This - Pointer to the SMM Access Interface.\r
- DescriptorIndex - Region of SMRAM to Close.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The region was successfully closed.\r
- EFI_DEVICE_ERROR - The region could not be closed because locked by\r
- chipset.\r
- EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
- BOOLEAN OpenState;\r
- UINTN Index;\r
-\r
- SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
- //\r
- // Cannot close a "locked" region\r
- //\r
- DEBUG ((EFI_D_WARN, "Cannot close the locked SMRAM Region\n"));\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (mSmmAccess.SMMRegionState & EFI_SMRAM_CLOSED) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Reset SMRAM cacheability to UC\r
- //\r
- for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
- DEBUG ((DEBUG_INFO, "SmmAccess->Close: Set to UC Base=%016lx Size=%016lx\n", SmmAccess->SmramDesc[Index].CpuStart, SmmAccess->SmramDesc[Index].PhysicalSize));\r
- Status = gDS->SetMemorySpaceAttributes(\r
- SmmAccess->SmramDesc[Index].CpuStart,\r
- SmmAccess->SmramDesc[Index].PhysicalSize,\r
- EFI_MEMORY_UC\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_WARN, "SmmAccess: Failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
- }\r
- }\r
-\r
- //\r
- // Close TSEG\r
- //\r
- if (!QNCCloseSmramRegion ()) {\r
- mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- mSmmAccess.SMMRegionState &= ~EFI_SMRAM_OPEN;\r
- SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));\r
- mSmmAccess.SMMRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
- SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
-\r
- //\r
- // Find out if any regions are still open\r
- //\r
- OpenState = FALSE;\r
- for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
- if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {\r
- OpenState = TRUE;\r
- }\r
- }\r
-\r
- SmmAccess->SmmAccess.OpenState = OpenState;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-Lock (\r
- IN EFI_SMM_ACCESS2_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine accepts a request to "lock" SMRAM. The\r
- region could be legacy AB or TSEG near top of physical memory.\r
- The use of "lock" means that the memory can no longer be opened\r
- to BS state..\r
-\r
-Arguments:\r
-\r
- This - Pointer to the SMM Access Interface.\r
- DescriptorIndex - Region of SMRAM to Lock.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The region was successfully locked.\r
- EFI_DEVICE_ERROR - The region could not be locked because at least\r
- one range is still open.\r
- EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
-\r
---*/\r
-{\r
- SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
-\r
- SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (SmmAccess->SmmAccess.OpenState) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
- SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);\r
- SmmAccess->SmmAccess.LockState = TRUE;\r
-\r
- //\r
- // Lock TSEG\r
- //\r
- QNCLockSmramRegion ();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-GetCapabilities (\r
- IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,\r
- IN OUT UINTN *SmramMapSize,\r
- IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine services a user request to discover the SMRAM\r
- capabilities of this platform. This will report the possible\r
- ranges that are possible for SMRAM access, based upon the\r
- memory controller capabilities.\r
-\r
-Arguments:\r
-\r
- This - Pointer to the SMRAM Access Interface.\r
- SmramMapSize - Pointer to the variable containing size of the\r
- buffer to contain the description information.\r
- SmramMap - Buffer containing the data describing the Smram\r
- region descriptors.\r
-Returns:\r
-\r
- EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.\r
- EFI_SUCCESS - The user provided a sufficiently-sized buffer.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
- UINTN BufferSize;\r
-\r
- SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
- BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);\r
-\r
- if (*SmramMapSize < BufferSize) {\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- } else {\r
- CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);\r
- Status = EFI_SUCCESS;\r
- }\r
- *SmramMapSize = BufferSize;\r
-\r
- return Status;\r
-}\r
-\r
-VOID\r
-SmmAccessOnBoot (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
-)\r
-{\r
-\r
-}\r
-VOID\r
-SyncRegionState2SmramDesc(\r
- IN BOOLEAN OrAnd,\r
- IN UINT64 Value\r
- )\r
-{\r
- UINT32 Index;\r
-\r
- for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
- if (OrAnd) {\r
- mSmmAccess.SmramDesc[Index].RegionState |= Value;\r
- } else {\r
- mSmmAccess.SmramDesc[Index].RegionState &= Value;\r
- }\r
- }\r
-}\r