]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/SmmAccess/SmramInternal.c
OvmfPkg/Csm/LegacyBiosDxe: Fix Legacy16GetTableAddress call for E820 data
[mirror_edk2.git] / OvmfPkg / SmmAccess / SmramInternal.c
CommitLineData
9d560947
LE
1/** @file\r
2\r
3 Functions and types shared by the SMM accessor PEI and DXE modules.\r
4\r
5 Copyright (C) 2015, Red Hat, Inc.\r
6\r
b26f0cf9 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9d560947
LE
8\r
9**/\r
10\r
11#include <Guid/AcpiS3Context.h>\r
12#include <IndustryStandard/Q35MchIch9.h>\r
13#include <Library/DebugLib.h>\r
1372f8d3 14#include <Library/PcdLib.h>\r
9d560947
LE
15#include <Library/PciLib.h>\r
16\r
17#include "SmramInternal.h"\r
18\r
1372f8d3
LE
19//\r
20// The value of PcdQ35TsegMbytes is saved into this variable at module startup.\r
21//\r
22UINT16 mQ35TsegMbytes;\r
23\r
24/**\r
25 Save PcdQ35TsegMbytes into mQ35TsegMbytes.\r
26**/\r
27VOID\r
28InitQ35TsegMbytes (\r
29 VOID\r
30 )\r
31{\r
32 mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);\r
33}\r
34\r
9d560947
LE
35/**\r
36 Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and\r
37 OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,\r
38 from the D_LCK and T_EN bits.\r
39\r
40 PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on\r
41 the LockState and OpenState fields being up-to-date on entry, and they need\r
42 to restore the same invariant on exit, if they touch the bits in question.\r
43\r
44 @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is\r
45 locked.\r
46 @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE\r
47 iff SMRAM is open.\r
48**/\r
49VOID\r
50GetStates (\r
51 OUT BOOLEAN *LockState,\r
52 OUT BOOLEAN *OpenState\r
53)\r
54{\r
55 UINT8 SmramVal, EsmramcVal;\r
56\r
57 SmramVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM));\r
58 EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));\r
59\r
60 *LockState = !!(SmramVal & MCH_SMRAM_D_LCK);\r
61 *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN);\r
62}\r
63\r
64//\r
65// The functions below follow the PEI_SMM_ACCESS_PPI and\r
66// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This\r
67// pointers are removed (TSEG doesn't depend on them), and so is the\r
68// DescriptorIndex parameter (TSEG doesn't support range-wise locking).\r
69//\r
70// The LockState and OpenState members that are common to both\r
71// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in\r
72// isolation from the rest of the (non-shared) members.\r
73//\r
74\r
75EFI_STATUS\r
76SmramAccessOpen (\r
77 OUT BOOLEAN *LockState,\r
78 OUT BOOLEAN *OpenState\r
79 )\r
80{\r
81 //\r
82 // Open TSEG by clearing T_EN.\r
83 //\r
84 PciAnd8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC),\r
85 (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff));\r
86\r
87 GetStates (LockState, OpenState);\r
88 if (!*OpenState) {\r
89 return EFI_DEVICE_ERROR;\r
90 }\r
91 return EFI_SUCCESS;\r
92}\r
93\r
94EFI_STATUS\r
95SmramAccessClose (\r
96 OUT BOOLEAN *LockState,\r
97 OUT BOOLEAN *OpenState\r
98 )\r
99{\r
100 //\r
101 // Close TSEG by setting T_EN.\r
102 //\r
103 PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);\r
104\r
105 GetStates (LockState, OpenState);\r
106 if (*OpenState) {\r
107 return EFI_DEVICE_ERROR;\r
108 }\r
109 return EFI_SUCCESS;\r
110}\r
111\r
112EFI_STATUS\r
113SmramAccessLock (\r
114 OUT BOOLEAN *LockState,\r
115 IN OUT BOOLEAN *OpenState\r
116 )\r
117{\r
118 if (*OpenState) {\r
119 return EFI_DEVICE_ERROR;\r
120 }\r
121\r
122 //\r
123 // Close & lock TSEG by setting T_EN and D_LCK.\r
124 //\r
125 PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);\r
126 PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM), MCH_SMRAM_D_LCK);\r
127\r
128 GetStates (LockState, OpenState);\r
129 if (*OpenState || !*LockState) {\r
130 return EFI_DEVICE_ERROR;\r
131 }\r
132 return EFI_SUCCESS;\r
133}\r
134\r
135EFI_STATUS\r
136SmramAccessGetCapabilities (\r
137 IN BOOLEAN LockState,\r
138 IN BOOLEAN OpenState,\r
139 IN OUT UINTN *SmramMapSize,\r
140 IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
141 )\r
142{\r
143 UINTN OriginalSize;\r
144 UINT32 TsegMemoryBaseMb, TsegMemoryBase;\r
145 UINT64 CommonRegionState;\r
146 UINT8 TsegSizeBits;\r
147\r
148 OriginalSize = *SmramMapSize;\r
149 *SmramMapSize = DescIdxCount * sizeof *SmramMap;\r
150 if (OriginalSize < *SmramMapSize) {\r
151 return EFI_BUFFER_TOO_SMALL;\r
152 }\r
153\r
154 //\r
155 // Read the TSEG Memory Base register.\r
156 //\r
157 TsegMemoryBaseMb = PciRead32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB));\r
158 TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20;\r
159\r
160 //\r
161 // Precompute the region state bits that will be set for all regions.\r
162 //\r
163 CommonRegionState = (OpenState ? EFI_SMRAM_OPEN : EFI_SMRAM_CLOSED) |\r
164 (LockState ? EFI_SMRAM_LOCKED : 0) |\r
165 EFI_CACHEABLE;\r
166\r
167 //\r
168 // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the\r
169 // start of TSEG. We round up the size to whole pages, and we report it as\r
170 // EFI_ALLOCATED, so that the SMM_CORE stays away from it.\r
171 //\r
172 SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase;\r
173 SmramMap[DescIdxSmmS3ResumeState].CpuStart = TsegMemoryBase;\r
174 SmramMap[DescIdxSmmS3ResumeState].PhysicalSize =\r
175 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE)));\r
176 SmramMap[DescIdxSmmS3ResumeState].RegionState =\r
177 CommonRegionState | EFI_ALLOCATED;\r
178\r
179 //\r
180 // Get the TSEG size bits from the ESMRAMC register.\r
181 //\r
182 TsegSizeBits = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC)) &\r
183 MCH_ESMRAMC_TSEG_MASK;\r
184\r
185 //\r
186 // The second region is the main one, following the first.\r
187 //\r
188 SmramMap[DescIdxMain].PhysicalStart =\r
189 SmramMap[DescIdxSmmS3ResumeState].PhysicalStart +\r
190 SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;\r
191 SmramMap[DescIdxMain].CpuStart = SmramMap[DescIdxMain].PhysicalStart;\r
192 SmramMap[DescIdxMain].PhysicalSize =\r
193 (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB :\r
194 TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB :\r
6812bb7b
LE
195 TsegSizeBits == MCH_ESMRAMC_TSEG_1MB ? SIZE_1MB :\r
196 mQ35TsegMbytes * SIZE_1MB) -\r
197 SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;\r
9d560947
LE
198 SmramMap[DescIdxMain].RegionState = CommonRegionState;\r
199\r
200 return EFI_SUCCESS;\r
201}\r