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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "SmmAccessDriver.h"
21 SMM_ACCESS_PRIVATE_DATA mSmmAccess
;
31 SmmAccessDriverEntryPoint (
32 IN EFI_HANDLE ImageHandle
,
33 IN EFI_SYSTEM_TABLE
*SystemTable
39 Installs an SMM Access Protocol.
43 ImageHandle - Handle for the image of this driver.
44 SystemTable - Pointer to the EFI System Table.
48 EFI_SUCCESS - Protocol successfully started and installed.
49 EFI_UNSUPPORTED - Protocol can't be started.
50 EFI_NOT_FOUND - Protocol not found.
56 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
58 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK
*DescriptorBlock
;
59 EFI_HOB_GUID_TYPE
*GuidHob
;
63 // Initialize private data
65 ZeroMem (&mSmmAccess
, sizeof (mSmmAccess
));
67 Status
= gBS
->LocateProtocol (
68 &gEfiPciRootBridgeIoProtocolGuid
,
70 (VOID
**) &PciRootBridgeIo
72 ASSERT_EFI_ERROR (Status
);
75 // Build SMM related information
77 mSmmAccess
.Signature
= SMM_ACCESS_PRIVATE_DATA_SIGNATURE
;
78 mSmmAccess
.Handle
= NULL
;
79 mSmmAccess
.PciRootBridgeIo
= PciRootBridgeIo
;
84 GuidHob
= GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid
);
85 DescriptorBlock
= GET_GUID_HOB_DATA (GuidHob
);
86 ASSERT (DescriptorBlock
);
90 // Get CPU Max bus number
92 mSmmAccess
.MaxBusNumber
= PCI_BUS_NUMBER_QNC
;
93 for (Index
= 0; Index
< MAX_CPU_SOCKET
; Index
++) {
94 mSmmAccess
.SocketPopulated
[Index
] = TRUE
;
98 // Use the hob to publish SMRAM capabilities
100 ASSERT (DescriptorBlock
->NumberOfSmmReservedRegions
<= MAX_SMRAM_RANGES
);
101 for (Index
= 0; Index
< DescriptorBlock
->NumberOfSmmReservedRegions
; Index
++) {
102 mSmmAccess
.SmramDesc
[Index
].PhysicalStart
= DescriptorBlock
->Descriptor
[Index
].PhysicalStart
;
103 mSmmAccess
.SmramDesc
[Index
].CpuStart
= DescriptorBlock
->Descriptor
[Index
].CpuStart
;
104 mSmmAccess
.SmramDesc
[Index
].PhysicalSize
= DescriptorBlock
->Descriptor
[Index
].PhysicalSize
;
105 mSmmAccess
.SmramDesc
[Index
].RegionState
= DescriptorBlock
->Descriptor
[Index
].RegionState
;
106 DEBUG ((EFI_D_INFO
, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index
, mSmmAccess
.SmramDesc
[Index
].CpuStart
,
107 mSmmAccess
.SmramDesc
[Index
].PhysicalSize
));
110 mSmmAccess
.NumberRegions
= Index
;
111 mSmmAccess
.SmmAccess
.Open
= Open
;
112 mSmmAccess
.SmmAccess
.Close
= Close
;
113 mSmmAccess
.SmmAccess
.Lock
= Lock
;
114 mSmmAccess
.SmmAccess
.GetCapabilities
= GetCapabilities
;
115 mSmmAccess
.SmmAccess
.LockState
= FALSE
;
116 mSmmAccess
.SmmAccess
.OpenState
= FALSE
;
117 mSmmAccess
.SMMRegionState
= EFI_SMRAM_CLOSED
;
120 // Install our protocol interfaces on the device's handle
122 Status
= gBS
->InstallMultipleProtocolInterfaces (
124 &gEfiSmmAccess2ProtocolGuid
,
125 &mSmmAccess
.SmmAccess
,
128 ASSERT_EFI_ERROR (Status
);
130 DEBUG ((EFI_D_INFO
, "SMM Base: %08X\n", (UINT32
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalStart
)));
131 DEBUG ((EFI_D_INFO
, "SMM Size: %08X\n", (UINT32
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalSize
)));
133 mSmmAccess
.TsegSize
= (UINT8
)(mSmmAccess
.SmramDesc
[mSmmAccess
.NumberRegions
-1].PhysicalSize
);
135 // T Seg setting done in QPI RC
139 // Prior ReadyToBoot, lock CSEG
141 Status
= EfiCreateEventReadyToBootEx(
146 ASSERT (!EFI_ERROR (Status
));
153 IN EFI_SMM_ACCESS2_PROTOCOL
*This
159 This routine accepts a request to "open" a region of SMRAM. The
160 region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
161 The use of "open" means that the memory is visible from all boot-service
166 This - Pointer to the SMM Access Interface.
167 DescriptorIndex - Region of SMRAM to Open.
171 EFI_SUCCESS - The region was successfully opened.
172 EFI_DEVICE_ERROR - The region could not be opened because locked by
174 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
178 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
180 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
182 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_LOCKED
) {
183 DEBUG ((EFI_D_ERROR
, "Cannot open a locked SMRAM region\n"));
184 return EFI_DEVICE_ERROR
;
190 if (!QNCOpenSmramRegion ()) {
191 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
192 return EFI_DEVICE_ERROR
;
195 mSmmAccess
.SMMRegionState
&= ~(EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
196 SyncRegionState2SmramDesc(FALSE
, (UINT64
)(UINTN
)(~(EFI_SMRAM_CLOSED
| EFI_ALLOCATED
)));
197 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_OPEN
;
198 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_OPEN
);
199 SmmAccess
->SmmAccess
.OpenState
= TRUE
;
207 IN EFI_SMM_ACCESS2_PROTOCOL
*This
213 This routine accepts a request to "close" a region of SMRAM. This is valid for
214 compatible SMRAM region.
218 This - Pointer to the SMM Access Interface.
219 DescriptorIndex - Region of SMRAM to Close.
223 EFI_SUCCESS - The region was successfully closed.
224 EFI_DEVICE_ERROR - The region could not be closed because locked by
226 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
230 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
234 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
236 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_LOCKED
) {
238 // Cannot close a "locked" region
240 DEBUG ((EFI_D_WARN
, "Cannot close the locked SMRAM Region\n"));
241 return EFI_DEVICE_ERROR
;
244 if (mSmmAccess
.SMMRegionState
& EFI_SMRAM_CLOSED
) {
245 return EFI_DEVICE_ERROR
;
251 if (!QNCCloseSmramRegion ()) {
252 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
253 return EFI_DEVICE_ERROR
;
256 mSmmAccess
.SMMRegionState
&= ~EFI_SMRAM_OPEN
;
257 SyncRegionState2SmramDesc(FALSE
, (UINT64
)(UINTN
)(~EFI_SMRAM_OPEN
));
258 mSmmAccess
.SMMRegionState
|= (EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
259 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_CLOSED
| EFI_ALLOCATED
);
262 // Find out if any regions are still open
265 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
266 if ((SmmAccess
->SmramDesc
[Index
].RegionState
& EFI_SMRAM_OPEN
) == EFI_SMRAM_OPEN
) {
271 SmmAccess
->SmmAccess
.OpenState
= OpenState
;
279 IN EFI_SMM_ACCESS2_PROTOCOL
*This
285 This routine accepts a request to "lock" SMRAM. The
286 region could be legacy AB or TSEG near top of physical memory.
287 The use of "lock" means that the memory can no longer be opened
292 This - Pointer to the SMM Access Interface.
293 DescriptorIndex - Region of SMRAM to Lock.
297 EFI_SUCCESS - The region was successfully locked.
298 EFI_DEVICE_ERROR - The region could not be locked because at least
299 one range is still open.
300 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
304 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
306 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
308 if (SmmAccess
->SmmAccess
.OpenState
) {
309 return EFI_DEVICE_ERROR
;
312 mSmmAccess
.SMMRegionState
|= EFI_SMRAM_LOCKED
;
313 SyncRegionState2SmramDesc(TRUE
, EFI_SMRAM_LOCKED
);
314 SmmAccess
->SmmAccess
.LockState
= TRUE
;
319 QNCLockSmramRegion ();
327 IN CONST EFI_SMM_ACCESS2_PROTOCOL
*This
,
328 IN OUT UINTN
*SmramMapSize
,
329 IN OUT EFI_SMRAM_DESCRIPTOR
*SmramMap
335 This routine services a user request to discover the SMRAM
336 capabilities of this platform. This will report the possible
337 ranges that are possible for SMRAM access, based upon the
338 memory controller capabilities.
342 This - Pointer to the SMRAM Access Interface.
343 SmramMapSize - Pointer to the variable containing size of the
344 buffer to contain the description information.
345 SmramMap - Buffer containing the data describing the Smram
349 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
350 EFI_SUCCESS - The user provided a sufficiently-sized buffer.
355 SMM_ACCESS_PRIVATE_DATA
*SmmAccess
;
358 SmmAccess
= SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This
);
359 BufferSize
= SmmAccess
->NumberRegions
* sizeof (EFI_SMRAM_DESCRIPTOR
);
361 if (*SmramMapSize
< BufferSize
) {
362 Status
= EFI_BUFFER_TOO_SMALL
;
364 CopyMem (SmramMap
, SmmAccess
->SmramDesc
, *SmramMapSize
);
365 Status
= EFI_SUCCESS
;
367 *SmramMapSize
= BufferSize
;
381 SyncRegionState2SmramDesc(
388 for (Index
= 0; Index
< mSmmAccess
.NumberRegions
; Index
++) {
390 mSmmAccess
.SmramDesc
[Index
].RegionState
|= Value
;
392 mSmmAccess
.SmramDesc
[Index
].RegionState
&= Value
;