2 This is the driver that publishes the SMM Access Protocol
3 instance for the Tylersburg chipset.
5 Copyright (c) 2013-2019 Intel Corporation.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "SmmAccessDriver.h"
15 SMM_ACCESS_PRIVATE_DATA mSmmAccess
;
25 SmmAccessDriverEntryPoint (
26 IN EFI_HANDLE ImageHandle
,
27 IN EFI_SYSTEM_TABLE
*SystemTable
33 Installs an SMM Access Protocol.
37 ImageHandle - Handle for the image of this driver.
38 SystemTable - Pointer to the EFI System Table.
42 EFI_SUCCESS - Protocol successfully started and installed.
43 EFI_UNSUPPORTED - Protocol can't be started.
44 EFI_NOT_FOUND - Protocol not found.
50 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
52 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK
*DescriptorBlock
;
53 EFI_HOB_GUID_TYPE
*GuidHob
;
57 // Initialize private data
59 ZeroMem (&mSmmAccess
, sizeof (mSmmAccess
));
61 Status
= gBS
->LocateProtocol (
62 &gEfiPciRootBridgeIoProtocolGuid
,
64 (VOID
**) &PciRootBridgeIo
66 ASSERT_EFI_ERROR (Status
);
69 // Build SMM related information
71 mSmmAccess
.Signature
= SMM_ACCESS_PRIVATE_DATA_SIGNATURE
;
72 mSmmAccess
.Handle
= NULL
;
73 mSmmAccess
.PciRootBridgeIo
= PciRootBridgeIo
;
78 GuidHob
= GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid
);
79 DescriptorBlock
= GET_GUID_HOB_DATA (GuidHob
);
80 ASSERT (DescriptorBlock
);
84 // Get CPU Max bus number
86 mSmmAccess
.MaxBusNumber
= PCI_BUS_NUMBER_QNC
;
87 for (Index
= 0; Index
< MAX_CPU_SOCKET
; Index
++) {
88 mSmmAccess
.SocketPopulated
[Index
] = TRUE
;
92 // Use the hob to publish SMRAM capabilities
94 ASSERT (DescriptorBlock
->NumberOfSmmReservedRegions
<= MAX_SMRAM_RANGES
);
95 for (Index
= 0; Index
< DescriptorBlock
->NumberOfSmmReservedRegions
; Index
++) {
96 mSmmAccess
.SmramDesc
[Index
].PhysicalStart
= DescriptorBlock
->Descriptor
[Index
].PhysicalStart
;
97 mSmmAccess
.SmramDesc
[Index
].CpuStart
= DescriptorBlock
->Descriptor
[Index
].CpuStart
;
98 mSmmAccess
.SmramDesc
[Index
].PhysicalSize
= DescriptorBlock
->Descriptor
[Index
].PhysicalSize
;
99 mSmmAccess
.SmramDesc
[Index
].RegionState
= DescriptorBlock
->Descriptor
[Index
].RegionState
;
100 DEBUG ((EFI_D_INFO
, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index
, mSmmAccess
.SmramDesc
[Index
].CpuStart
,
101 mSmmAccess
.SmramDesc
[Index
].PhysicalSize
));
104 mSmmAccess
.NumberRegions
= Index
;
105 mSmmAccess
.SmmAccess
.Open
= Open
;
106 mSmmAccess
.SmmAccess
.Close
= Close
;
107 mSmmAccess
.SmmAccess
.Lock
= Lock
;
108 mSmmAccess
.SmmAccess
.GetCapabilities
= GetCapabilities
;
109 mSmmAccess
.SmmAccess
.LockState
= FALSE
;
110 mSmmAccess
.SmmAccess
.OpenState
= FALSE
;
111 mSmmAccess
.SMMRegionState
= EFI_SMRAM_CLOSED
;
114 // Install our protocol interfaces on the device's handle
116 Status
= gBS
->InstallMultipleProtocolInterfaces (
118 &gEfiSmmAccess2ProtocolGuid
,
119 &mSmmAccess
.SmmAccess
,
122 ASSERT_EFI_ERROR (Status
);
124 DEBUG ((EFI_D_INFO
, "SMM Base: %08X\n", (UINT32
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalStart
)));
125 DEBUG ((EFI_D_INFO
, "SMM Size: %08X\n", (UINT32
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalSize
)));
127 mSmmAccess
.TsegSize
= (UINT8
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalSize
);
129 // T Seg setting done in QPI RC
133 // Prior ReadyToBoot, lock CSEG
135 Status
= EfiCreateEventReadyToBootEx(
140 ASSERT (!EFI_ERROR (Status
));
147 IN EFI_SMM_ACCESS2_PROTOCOL
*This
153 This routine accepts a request to "open" a region of SMRAM. The
154 region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
155 The use of "open" means that the memory is visible from all boot-service
160 This - Pointer to the SMM Access Interface.
161 DescriptorIndex - Region of SMRAM to Open.
165 EFI_SUCCESS - The region was successfully opened.
166 EFI_DEVICE_ERROR - The region could not be opened because locked by
168 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
172 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
174 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
176 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_LOCKED
) {
177 DEBUG ((EFI_D_ERROR
, "Cannot open a locked SMRAM region\n"));
178 return EFI_DEVICE_ERROR
;
184 if (!QNCOpenSmramRegion ()) {
185 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
186 return EFI_DEVICE_ERROR
;
189 mSmmAccess
.SMMRegionState
&= ~(EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
190 SyncRegionState2SmramDesc(FALSE
, (UINT64
)(UINTN
)(~(EFI_SMRAM_CLOSED
| EFI_ALLOCATED
)));
191 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_OPEN
;
192 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_OPEN
);
193 SmmAccess
->SmmAccess
.OpenState
= TRUE
;
201 IN EFI_SMM_ACCESS2_PROTOCOL
*This
207 This routine accepts a request to "close" a region of SMRAM. This is valid for
208 compatible SMRAM region.
212 This - Pointer to the SMM Access Interface.
213 DescriptorIndex - Region of SMRAM to Close.
217 EFI_SUCCESS - The region was successfully closed.
218 EFI_DEVICE_ERROR - The region could not be closed because locked by
220 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
225 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
229 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
231 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_LOCKED
) {
233 // Cannot close a "locked" region
235 DEBUG ((EFI_D_WARN
, "Cannot close the locked SMRAM Region\n"));
236 return EFI_DEVICE_ERROR
;
239 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_CLOSED
) {
240 return EFI_DEVICE_ERROR
;
244 // Reset SMRAM cacheability to UC
246 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
247 DEBUG ((DEBUG_INFO
, "SmmAccess->Close: Set to UC Base=%016lx Size=%016lx\n", SmmAccess
->SmramDesc
[Index
].CpuStart
, SmmAccess
->SmramDesc
[Index
].PhysicalSize
));
248 Status
= gDS
->SetMemorySpaceAttributes(
249 SmmAccess
->SmramDesc
[Index
].CpuStart
,
250 SmmAccess
->SmramDesc
[Index
].PhysicalSize
,
253 if (EFI_ERROR (Status
)) {
254 DEBUG ((DEBUG_WARN
, "SmmAccess: Failed to reset SMRAM window to EFI_MEMORY_UC\n"));
261 if (!QNCCloseSmramRegion ()) {
262 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
263 return EFI_DEVICE_ERROR
;
266 mSmmAccess
.SMMRegionState
&= ~EFI_SMRAM_OPEN
;
267 SyncRegionState2SmramDesc(FALSE
, (UINT64
)(UINTN
)(~EFI_SMRAM_OPEN
));
268 mSmmAccess
.SMMRegionState
|= (EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
269 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
272 // Find out if any regions are still open
275 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
276 if ((SmmAccess
->SmramDesc
[Index
].RegionState
& EFI_SMRAM_OPEN
) == EFI_SMRAM_OPEN
) {
281 SmmAccess
->SmmAccess
.OpenState
= OpenState
;
289 IN EFI_SMM_ACCESS2_PROTOCOL
*This
295 This routine accepts a request to "lock" SMRAM. The
296 region could be legacy AB or TSEG near top of physical memory.
297 The use of "lock" means that the memory can no longer be opened
302 This - Pointer to the SMM Access Interface.
303 DescriptorIndex - Region of SMRAM to Lock.
307 EFI_SUCCESS - The region was successfully locked.
308 EFI_DEVICE_ERROR - The region could not be locked because at least
309 one range is still open.
310 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
314 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
316 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
318 if (SmmAccess
->SmmAccess
.OpenState
) {
319 return EFI_DEVICE_ERROR
;
322 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
323 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_LOCKED
);
324 SmmAccess
->SmmAccess
.LockState
= TRUE
;
329 QNCLockSmramRegion ();
337 IN CONST EFI_SMM_ACCESS2_PROTOCOL
*This
,
338 IN OUT UINTN
*SmramMapSize
,
339 IN OUT EFI_SMRAM_DESCRIPTOR
*SmramMap
345 This routine services a user request to discover the SMRAM
346 capabilities of this platform. This will report the possible
347 ranges that are possible for SMRAM access, based upon the
348 memory controller capabilities.
352 This - Pointer to the SMRAM Access Interface.
353 SmramMapSize - Pointer to the variable containing size of the
354 buffer to contain the description information.
355 SmramMap - Buffer containing the data describing the Smram
359 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
360 EFI_SUCCESS - The user provided a sufficiently-sized buffer.
365 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
368 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
369 BufferSize
= SmmAccess
->NumberRegions
* sizeof (EFI_SMRAM_DESCRIPTOR
);
371 if (*SmramMapSize
< BufferSize
) {
372 Status
= EFI_BUFFER_TOO_SMALL
;
374 CopyMem (SmramMap
, SmmAccess
->SmramDesc
, *SmramMapSize
);
375 Status
= EFI_SUCCESS
;
377 *SmramMapSize
= BufferSize
;
391 SyncRegionState2SmramDesc(
398 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
400 mSmmAccess
.SmramDesc
[Index
].RegionState
|= Value
;
402 mSmmAccess
.SmramDesc
[Index
].RegionState
&= Value
;