1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
/** @file
Functions and types shared by the SMM accessor PEI and DXE modules.
Copyright (C) 2015, Red Hat, Inc.
Copyright (c) 2024 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <IndustryStandard/Q35MchIch9.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/PciLib.h>
#include "SmramInternal.h"
//
// The value of PcdQ35TsegMbytes is saved into this variable at module startup.
//
UINT16 mQ35TsegMbytes;
//
// The value of PcdQ35SmramAtDefaultSmbase is saved into this variable at
// module startup.
//
STATIC BOOLEAN mQ35SmramAtDefaultSmbase;
/**
Save PcdQ35TsegMbytes into mQ35TsegMbytes.
**/
VOID
InitQ35TsegMbytes (
VOID
)
{
mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
}
/**
Save PcdQ35SmramAtDefaultSmbase into mQ35SmramAtDefaultSmbase.
**/
VOID
InitQ35SmramAtDefaultSmbase (
VOID
)
{
mQ35SmramAtDefaultSmbase = PcdGetBool (PcdQ35SmramAtDefaultSmbase);
}
/**
Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and
OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,
from the D_LCK and T_EN bits.
PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on
the LockState and OpenState fields being up-to-date on entry, and they need
to restore the same invariant on exit, if they touch the bits in question.
@param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is
locked.
@param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE
iff SMRAM is open.
**/
VOID
GetStates (
OUT BOOLEAN *LockState,
OUT BOOLEAN *OpenState
)
{
UINT8 SmramVal, EsmramcVal;
SmramVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM));
EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));
*LockState = !!(SmramVal & MCH_SMRAM_D_LCK);
*OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN);
}
//
// The functions below follow the PEI_SMM_ACCESS_PPI and
// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This
// pointers are removed (TSEG doesn't depend on them), and so is the
// DescriptorIndex parameter (TSEG doesn't support range-wise locking).
//
// The LockState and OpenState members that are common to both
// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in
// isolation from the rest of the (non-shared) members.
//
EFI_STATUS
SmramAccessOpen (
OUT BOOLEAN *LockState,
OUT BOOLEAN *OpenState
)
{
//
// Open TSEG by clearing T_EN.
//
PciAnd8 (
DRAMC_REGISTER_Q35 (MCH_ESMRAMC),
(UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff)
);
GetStates (LockState, OpenState);
if (!*OpenState) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
SmramAccessClose (
OUT BOOLEAN *LockState,
OUT BOOLEAN *OpenState
)
{
//
// Close TSEG by setting T_EN.
//
PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);
GetStates (LockState, OpenState);
if (*OpenState) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
SmramAccessLock (
OUT BOOLEAN *LockState,
IN OUT BOOLEAN *OpenState
)
{
if (*OpenState) {
return EFI_DEVICE_ERROR;
}
//
// Close & lock TSEG by setting T_EN and D_LCK.
//
PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);
PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM), MCH_SMRAM_D_LCK);
//
// Close & lock the SMRAM at the default SMBASE, if it exists.
//
if (mQ35SmramAtDefaultSmbase) {
PciWrite8 (
DRAMC_REGISTER_Q35 (MCH_DEFAULT_SMBASE_CTL),
MCH_DEFAULT_SMBASE_LCK
);
}
GetStates (LockState, OpenState);
if (*OpenState || !*LockState) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
SmramAccessGetCapabilities (
IN OUT UINTN *SmramMapSize,
IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
)
{
UINTN BufferSize;
EFI_HOB_GUID_TYPE *GuidHob;
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
UINTN Index;
//
// Get Hob list
//
GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
ASSERT (DescriptorBlock);
BufferSize = DescriptorBlock->NumberOfSmmReservedRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
if (*SmramMapSize < BufferSize) {
*SmramMapSize = BufferSize;
return EFI_BUFFER_TOO_SMALL;
}
//
// Update SmramMapSize to real return SMRAM map size
//
*SmramMapSize = BufferSize;
//
// Use the hob to publish SMRAM capabilities
//
for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
SmramMap[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
SmramMap[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;
SmramMap[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;
SmramMap[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;
}
return EFI_SUCCESS;
}
|