]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/SmmAccessDxe/SmmAccessDxe.c
UefiPayloadPkg: Add a common SmmAccessDxe module
[mirror_edk2.git] / UefiPayloadPkg / SmmAccessDxe / SmmAccessDxe.c
1 /** @file
2 This driver publishes the SMM Access 2 Protocol.
3
4 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "SmmAccessDxe.h"
10
11 SMM_ACCESS_PRIVATE_DATA mSmmAccess;
12
13 /**
14 Update region state from SMRAM description
15
16 @param[in] OrLogic Indicate to use OR if true or AND if false.
17 @param[in] Value The value to set to region state based on OrLogic.
18
19 **/
20 VOID
21 SyncRegionState2SmramDesc(
22 IN BOOLEAN OrLogic,
23 IN UINT64 Value
24 )
25 {
26 UINT32 Index;
27
28 for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
29 if (OrLogic) {
30 mSmmAccess.SmramDesc[Index].RegionState |= Value;
31 } else {
32 mSmmAccess.SmramDesc[Index].RegionState &= Value;
33 }
34 }
35 }
36
37 /**
38 This routine accepts a request to "open" a region of SMRAM. The
39 region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
40 The use of "open" means that the memory is visible from all boot-service
41 and SMM agents.
42
43 @param This Pointer to the SMM Access Interface.
44
45 @retval EFI_SUCCESS The region was successfully opened.
46 @retval EFI_DEVICE_ERROR The region could not be opened because locked by chipset.
47 @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
48
49 **/
50 EFI_STATUS
51 EFIAPI
52 Open (
53 IN EFI_SMM_ACCESS2_PROTOCOL *This
54 )
55 {
56 if ((mSmmAccess.SmmRegionState & EFI_SMRAM_LOCKED) != 0) {
57 //
58 // Cannot open a "locked" region
59 //
60 DEBUG ((DEBUG_INFO, "Cannot open the locked SMRAM Region\n"));
61 return EFI_DEVICE_ERROR;
62 }
63
64 mSmmAccess.SmmRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
65 SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED)));
66
67 mSmmAccess.SmmRegionState |= EFI_SMRAM_OPEN;
68 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_OPEN);
69 mSmmAccess.SmmAccess.OpenState = TRUE;
70
71 return EFI_SUCCESS;
72 }
73
74 /**
75 This routine accepts a request to "close" a region of SMRAM. The region
76 could be legacy AB or TSEG near top of physical memory.
77 The use of "close" means that the memory is only visible from SMM agents,
78 not from BS or RT code.
79
80 @param This Pointer to the SMM Access Interface.
81
82 @retval EFI_SUCCESS The region was successfully closed.
83 @retval EFI_DEVICE_ERROR The region could not be closed because locked by
84 chipset.
85 @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
86
87 **/
88 EFI_STATUS
89 EFIAPI
90 Close (
91 IN EFI_SMM_ACCESS2_PROTOCOL *This
92 )
93 {
94 if ((mSmmAccess.SmmRegionState & EFI_SMRAM_LOCKED) != 0) {
95 //
96 // Cannot close a "locked" region
97 //
98 DEBUG ((DEBUG_INFO, "Cannot close the locked SMRAM Region\n"));
99 return EFI_DEVICE_ERROR;
100 }
101
102 if ((mSmmAccess.SmmRegionState & EFI_SMRAM_CLOSED) != 0) {
103 return EFI_DEVICE_ERROR;
104 }
105
106 mSmmAccess.SmmRegionState &= ~EFI_SMRAM_OPEN;
107 SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));
108
109 mSmmAccess.SmmRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
110 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);
111
112 mSmmAccess.SmmAccess.OpenState = FALSE;
113
114 return EFI_SUCCESS;
115 }
116
117 /**
118 This routine accepts a request to "lock" SMRAM. The
119 region could be legacy AB or TSEG near top of physical memory.
120 The use of "lock" means that the memory can no longer be opened
121 to BS state.
122
123 @param This Pointer to the SMM Access Interface.
124
125 @retval EFI_SUCCESS The region was successfully locked.
126 @retval EFI_DEVICE_ERROR The region could not be locked because at least
127 one range is still open.
128 @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.
129
130 **/
131 EFI_STATUS
132 EFIAPI
133 Lock (
134 IN EFI_SMM_ACCESS2_PROTOCOL *This
135 )
136 {
137 if (mSmmAccess.SmmAccess.OpenState) {
138 DEBUG ((DEBUG_INFO, "Cannot lock SMRAM when it is still open\n"));
139 return EFI_DEVICE_ERROR;
140 }
141
142 mSmmAccess.SmmRegionState |= EFI_SMRAM_LOCKED;
143 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);
144 mSmmAccess.SmmAccess.LockState = TRUE;
145 return EFI_SUCCESS;
146 }
147
148 /**
149 This routine services a user request to discover the SMRAM
150 capabilities of this platform. This will report the possible
151 ranges that are possible for SMRAM access, based upon the
152 memory controller capabilities.
153
154 @param This Pointer to the SMRAM Access Interface.
155 @param SmramMapSize Pointer to the variable containing size of the
156 buffer to contain the description information.
157 @param SmramMap Buffer containing the data describing the Smram
158 region descriptors.
159
160 @retval EFI_BUFFER_TOO_SMALL The user did not provide a sufficient buffer.
161 @retval EFI_SUCCESS The user provided a sufficiently-sized buffer.
162
163 **/
164 EFI_STATUS
165 EFIAPI
166 GetCapabilities (
167 IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
168 IN OUT UINTN *SmramMapSize,
169 IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
170 )
171 {
172 EFI_STATUS Status;
173 UINTN NecessaryBufferSize;
174
175 NecessaryBufferSize = mSmmAccess.NumberRegions * sizeof(EFI_SMRAM_DESCRIPTOR);
176 if (*SmramMapSize < NecessaryBufferSize) {
177 Status = EFI_BUFFER_TOO_SMALL;
178 } else {
179 CopyMem(SmramMap, mSmmAccess.SmramDesc, NecessaryBufferSize);
180 Status = EFI_SUCCESS;
181 }
182
183 *SmramMapSize = NecessaryBufferSize;
184 return Status;
185 }
186
187 /**
188 This function installs EFI_SMM_ACCESS_PROTOCOL.
189
190 @param ImageHandle Handle for the image of this driver
191 @param SystemTable Pointer to the EFI System Table
192
193 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
194 @return The status returned from InstallProtocolInterface().
195
196 **/
197 EFI_STATUS
198 EFIAPI
199 SmmAccessEntryPoint (
200 IN EFI_HANDLE ImageHandle,
201 IN EFI_SYSTEM_TABLE *SystemTable
202 )
203 {
204 EFI_STATUS Status;
205 EFI_HOB_GUID_TYPE *GuidHob;
206 UINT32 SmmRegionNum;
207 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHob;
208 UINT32 Index;
209
210 //
211 // Get SMRAM info HOB
212 //
213 GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
214 if (GuidHob == NULL) {
215 DEBUG ((DEBUG_INFO, "SMRAM HOB NOT found\n"));
216 return EFI_NOT_FOUND;
217 }
218 SmramHob = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *) GET_GUID_HOB_DATA(GuidHob);
219 SmmRegionNum = SmramHob->NumberOfSmmReservedRegions;
220 mSmmAccess.SmramDesc = AllocateZeroPool (sizeof (EFI_SMRAM_DESCRIPTOR) * SmmRegionNum);
221 if (mSmmAccess.SmramDesc == NULL) {
222 return EFI_OUT_OF_RESOURCES;
223 }
224 CopyMem (mSmmAccess.SmramDesc, &SmramHob->Descriptor, sizeof (EFI_SMRAM_DESCRIPTOR) * SmmRegionNum);
225
226 DEBUG ((DEBUG_INFO, "NumberOfSmmReservedRegions = 0x%x\n", SmmRegionNum));
227 for (Index = 0; Index < SmmRegionNum; Index++) {
228 DEBUG ((DEBUG_INFO, "%d: base=0x%x, size = 0x%x, State=0x%x\n",Index,
229 SmramHob->Descriptor[Index].PhysicalStart,
230 SmramHob->Descriptor[Index].PhysicalSize,
231 SmramHob->Descriptor[Index].RegionState));
232 mSmmAccess.SmramDesc[Index].RegionState &= EFI_ALLOCATED;
233 mSmmAccess.SmramDesc[Index].RegionState |= EFI_SMRAM_CLOSED | EFI_CACHEABLE;
234 }
235
236 mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
237 mSmmAccess.NumberRegions = SmmRegionNum;
238 mSmmAccess.SmmAccess.Open = Open;
239 mSmmAccess.SmmAccess.Close = Close;
240 mSmmAccess.SmmAccess.Lock = Lock;
241 mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities;
242 mSmmAccess.SmmAccess.LockState = FALSE;
243 mSmmAccess.SmmAccess.OpenState = FALSE;
244 mSmmAccess.SmmRegionState = EFI_SMRAM_CLOSED;
245
246 Status = gBS->InstallMultipleProtocolInterfaces (
247 &mSmmAccess.Handle,
248 &gEfiSmmAccess2ProtocolGuid,
249 &mSmmAccess.SmmAccess,
250 NULL
251 );
252
253 return Status;
254 }