3 Functions and types shared by the SMM accessor PEI and DXE modules.
5 Copyright (C) 2015, Red Hat, Inc.
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 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, WITHOUT
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Guid/AcpiS3Context.h>
18 #include <IndustryStandard/Q35MchIch9.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PciLib.h>
22 #include "SmramInternal.h"
25 Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and
26 OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,
27 from the D_LCK and T_EN bits.
29 PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on
30 the LockState and OpenState fields being up-to-date on entry, and they need
31 to restore the same invariant on exit, if they touch the bits in question.
33 @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is
35 @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE
40 OUT BOOLEAN
*LockState
,
41 OUT BOOLEAN
*OpenState
44 UINT8 SmramVal
, EsmramcVal
;
46 SmramVal
= PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM
));
47 EsmramcVal
= PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC
));
49 *LockState
= !!(SmramVal
& MCH_SMRAM_D_LCK
);
50 *OpenState
= !(EsmramcVal
& MCH_ESMRAMC_T_EN
);
54 // The functions below follow the PEI_SMM_ACCESS_PPI and
55 // EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This
56 // pointers are removed (TSEG doesn't depend on them), and so is the
57 // DescriptorIndex parameter (TSEG doesn't support range-wise locking).
59 // The LockState and OpenState members that are common to both
60 // PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in
61 // isolation from the rest of the (non-shared) members.
66 OUT BOOLEAN
*LockState
,
67 OUT BOOLEAN
*OpenState
71 // Open TSEG by clearing T_EN.
73 PciAnd8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC
),
74 (UINT8
)((~(UINT32
)MCH_ESMRAMC_T_EN
) & 0xff));
76 GetStates (LockState
, OpenState
);
78 return EFI_DEVICE_ERROR
;
85 OUT BOOLEAN
*LockState
,
86 OUT BOOLEAN
*OpenState
90 // Close TSEG by setting T_EN.
92 PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC
), MCH_ESMRAMC_T_EN
);
94 GetStates (LockState
, OpenState
);
96 return EFI_DEVICE_ERROR
;
103 OUT BOOLEAN
*LockState
,
104 IN OUT BOOLEAN
*OpenState
108 return EFI_DEVICE_ERROR
;
112 // Close & lock TSEG by setting T_EN and D_LCK.
114 PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC
), MCH_ESMRAMC_T_EN
);
115 PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM
), MCH_SMRAM_D_LCK
);
117 GetStates (LockState
, OpenState
);
118 if (*OpenState
|| !*LockState
) {
119 return EFI_DEVICE_ERROR
;
125 SmramAccessGetCapabilities (
126 IN BOOLEAN LockState
,
127 IN BOOLEAN OpenState
,
128 IN OUT UINTN
*SmramMapSize
,
129 IN OUT EFI_SMRAM_DESCRIPTOR
*SmramMap
133 UINT32 TsegMemoryBaseMb
, TsegMemoryBase
;
134 UINT64 CommonRegionState
;
137 OriginalSize
= *SmramMapSize
;
138 *SmramMapSize
= DescIdxCount
* sizeof *SmramMap
;
139 if (OriginalSize
< *SmramMapSize
) {
140 return EFI_BUFFER_TOO_SMALL
;
144 // Read the TSEG Memory Base register.
146 TsegMemoryBaseMb
= PciRead32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB
));
147 TsegMemoryBase
= (TsegMemoryBaseMb
>> MCH_TSEGMB_MB_SHIFT
) << 20;
150 // Precompute the region state bits that will be set for all regions.
152 CommonRegionState
= (OpenState
? EFI_SMRAM_OPEN
: EFI_SMRAM_CLOSED
) |
153 (LockState
? EFI_SMRAM_LOCKED
: 0) |
157 // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the
158 // start of TSEG. We round up the size to whole pages, and we report it as
159 // EFI_ALLOCATED, so that the SMM_CORE stays away from it.
161 SmramMap
[DescIdxSmmS3ResumeState
].PhysicalStart
= TsegMemoryBase
;
162 SmramMap
[DescIdxSmmS3ResumeState
].CpuStart
= TsegMemoryBase
;
163 SmramMap
[DescIdxSmmS3ResumeState
].PhysicalSize
=
164 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE
)));
165 SmramMap
[DescIdxSmmS3ResumeState
].RegionState
=
166 CommonRegionState
| EFI_ALLOCATED
;
169 // Get the TSEG size bits from the ESMRAMC register.
171 TsegSizeBits
= PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC
)) &
172 MCH_ESMRAMC_TSEG_MASK
;
175 // The second region is the main one, following the first.
177 SmramMap
[DescIdxMain
].PhysicalStart
=
178 SmramMap
[DescIdxSmmS3ResumeState
].PhysicalStart
+
179 SmramMap
[DescIdxSmmS3ResumeState
].PhysicalSize
;
180 SmramMap
[DescIdxMain
].CpuStart
= SmramMap
[DescIdxMain
].PhysicalStart
;
181 SmramMap
[DescIdxMain
].PhysicalSize
=
182 (TsegSizeBits
== MCH_ESMRAMC_TSEG_8MB
? SIZE_8MB
:
183 TsegSizeBits
== MCH_ESMRAMC_TSEG_2MB
? SIZE_2MB
:
184 SIZE_1MB
) - SmramMap
[DescIdxSmmS3ResumeState
].PhysicalSize
;
185 SmramMap
[DescIdxMain
].RegionState
= CommonRegionState
;