2 This is the driver that publishes the SMM Access Protocol
3 instance for the Tylersburg chipset.
5 Copyright (c) 2013-2015 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.
224 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
228 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
230 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_LOCKED
) {
232 // Cannot close a "locked" region
234 DEBUG ((EFI_D_WARN
, "Cannot close the locked SMRAM Region\n"));
235 return EFI_DEVICE_ERROR
;
238 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_CLOSED
) {
239 return EFI_DEVICE_ERROR
;
245 if (!QNCCloseSmramRegion ()) {
246 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
247 return EFI_DEVICE_ERROR
;
250 mSmmAccess
.SMMRegionState
&= ~EFI_SMRAM_OPEN
;
251 SyncRegionState2SmramDesc(FALSE
, (UINT64
)(UINTN
)(~EFI_SMRAM_OPEN
));
252 mSmmAccess
.SMMRegionState
|= (EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
253 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
256 // Find out if any regions are still open
259 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
260 if ((SmmAccess
->SmramDesc
[Index
].RegionState
& EFI_SMRAM_OPEN
) == EFI_SMRAM_OPEN
) {
265 SmmAccess
->SmmAccess
.OpenState
= OpenState
;
273 IN EFI_SMM_ACCESS2_PROTOCOL
*This
279 This routine accepts a request to "lock" SMRAM. The
280 region could be legacy AB or TSEG near top of physical memory.
281 The use of "lock" means that the memory can no longer be opened
286 This - Pointer to the SMM Access Interface.
287 DescriptorIndex - Region of SMRAM to Lock.
291 EFI_SUCCESS - The region was successfully locked.
292 EFI_DEVICE_ERROR - The region could not be locked because at least
293 one range is still open.
294 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
298 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
300 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
302 if (SmmAccess
->SmmAccess
.OpenState
) {
303 return EFI_DEVICE_ERROR
;
306 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
307 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_LOCKED
);
308 SmmAccess
->SmmAccess
.LockState
= TRUE
;
313 QNCLockSmramRegion ();
321 IN CONST EFI_SMM_ACCESS2_PROTOCOL
*This
,
322 IN OUT UINTN
*SmramMapSize
,
323 IN OUT EFI_SMRAM_DESCRIPTOR
*SmramMap
329 This routine services a user request to discover the SMRAM
330 capabilities of this platform. This will report the possible
331 ranges that are possible for SMRAM access, based upon the
332 memory controller capabilities.
336 This - Pointer to the SMRAM Access Interface.
337 SmramMapSize - Pointer to the variable containing size of the
338 buffer to contain the description information.
339 SmramMap - Buffer containing the data describing the Smram
343 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
344 EFI_SUCCESS - The user provided a sufficiently-sized buffer.
349 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
352 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
353 BufferSize
= SmmAccess
->NumberRegions
* sizeof (EFI_SMRAM_DESCRIPTOR
);
355 if (*SmramMapSize
< BufferSize
) {
356 Status
= EFI_BUFFER_TOO_SMALL
;
358 CopyMem (SmramMap
, SmmAccess
->SmramDesc
, *SmramMapSize
);
359 Status
= EFI_SUCCESS
;
361 *SmramMapSize
= BufferSize
;
375 SyncRegionState2SmramDesc(
382 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
384 mSmmAccess
.SmramDesc
[Index
].RegionState
|= Value
;
386 mSmmAccess
.SmramDesc
[Index
].RegionState
&= Value
;