VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/SmmAccess/SmramInternal.c@ 99404

Last change on this file since 99404 was 99404, checked in by vboxsync, 22 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette