]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
MdeModulePkg: Add SMM LockBox
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
1 /** @file
2
3 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <PiSmm.h>
17 #include <Library/UefiDriverEntryPoint.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiRuntimeServicesTableLib.h>
20 #include <Library/SmmServicesTableLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/LockBoxLib.h>
25 #include <Protocol/SmmReadyToLock.h>
26 #include <Protocol/SmmCommunication.h>
27 #include <Protocol/SmmAccess2.h>
28 #include <Protocol/LockBox.h>
29 #include <Guid/SmmLockBox.h>
30
31 BOOLEAN mLocked = FALSE;
32
33 EFI_SMRAM_DESCRIPTOR *mSmramRanges;
34 UINTN mSmramRangeCount;
35
36 /**
37 This function check if the address is in SMRAM.
38
39 @param Buffer the buffer address to be checked.
40 @param Length the buffer length to be checked.
41
42 @retval TRUE this address is in SMRAM.
43 @retval FALSE this address is NOT in SMRAM.
44 **/
45 BOOLEAN
46 IsAddressInSmram (
47 IN EFI_PHYSICAL_ADDRESS Buffer,
48 IN UINT64 Length
49 )
50 {
51 UINTN Index;
52
53 for (Index = 0; Index < mSmramRangeCount; Index ++) {
54 if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||
55 ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {
56 return TRUE;
57 }
58 }
59
60 return FALSE;
61 }
62
63 /**
64 Dispatch function for SMM lock box save.
65
66 @param LockBoxParameterSave parameter of lock box save
67 **/
68 VOID
69 SmmLockBoxSave (
70 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave
71 )
72 {
73 EFI_STATUS Status;
74
75 //
76 // Sanity check
77 //
78 if (mLocked) {
79 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
80 LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
81 return ;
82 }
83
84 //
85 // Save data
86 //
87 Status = SaveLockBox (
88 &LockBoxParameterSave->Guid,
89 (VOID *)(UINTN)LockBoxParameterSave->Buffer,
90 (UINTN)LockBoxParameterSave->Length
91 );
92 LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;
93 return ;
94 }
95
96 /**
97 Dispatch function for SMM lock box set attributes.
98
99 @param LockBoxParameterSetAttributes parameter of lock box set attributes
100 **/
101 VOID
102 SmmLockBoxSetAttributes (
103 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes
104 )
105 {
106 EFI_STATUS Status;
107
108 //
109 // Sanity check
110 //
111 if (mLocked) {
112 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
113 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
114 return ;
115 }
116
117 //
118 // Update data
119 //
120 Status = SetLockBoxAttributes (
121 &LockBoxParameterSetAttributes->Guid,
122 LockBoxParameterSetAttributes->Attributes
123 );
124 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;
125 return ;
126 }
127
128 /**
129 Dispatch function for SMM lock box update.
130
131 @param LockBoxParameterUpdate parameter of lock box update
132 **/
133 VOID
134 SmmLockBoxUpdate (
135 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate
136 )
137 {
138 EFI_STATUS Status;
139
140 //
141 // Sanity check
142 //
143 if (mLocked) {
144 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));
145 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
146 return ;
147 }
148
149 //
150 // Update data
151 //
152 Status = UpdateLockBox (
153 &LockBoxParameterUpdate->Guid,
154 (UINTN)LockBoxParameterUpdate->Offset,
155 (VOID *)(UINTN)LockBoxParameterUpdate->Buffer,
156 (UINTN)LockBoxParameterUpdate->Length
157 );
158 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;
159 return ;
160 }
161
162 /**
163 Dispatch function for SMM lock box restore.
164
165 @param LockBoxParameterRestore parameter of lock box restore
166 **/
167 VOID
168 SmmLockBoxRestore (
169 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore
170 )
171 {
172 EFI_STATUS Status;
173
174 //
175 // Sanity check
176 //
177 if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) {
178 DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));
179 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
180 return ;
181 }
182
183 //
184 // Restore data
185 //
186 Status = RestoreLockBox (
187 &LockBoxParameterRestore->Guid,
188 (VOID *)(UINTN)LockBoxParameterRestore->Buffer,
189 (UINTN *)&LockBoxParameterRestore->Length
190 );
191 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
192 return ;
193 }
194
195 /**
196 Dispatch function for SMM lock box restore all in place.
197
198 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
199 **/
200 VOID
201 SmmLockBoxRestoreAllInPlace (
202 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace
203 )
204 {
205 EFI_STATUS Status;
206
207 Status = RestoreAllLockBoxInPlace ();
208 LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;
209 return ;
210 }
211
212 /**
213 Dispatch function for a Software SMI handler.
214
215 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
216 @param Context Points to an optional handler context which was specified when the
217 handler was registered.
218 @param CommBuffer A pointer to a collection of data in memory that will
219 be conveyed from a non-SMM environment into an SMM environment.
220 @param CommBufferSize The size of the CommBuffer.
221
222 @retval EFI_SUCCESS Command is handled successfully.
223
224 **/
225 EFI_STATUS
226 EFIAPI
227 SmmLockBoxHandler (
228 IN EFI_HANDLE DispatchHandle,
229 IN CONST VOID *Context OPTIONAL,
230 IN OUT VOID *CommBuffer OPTIONAL,
231 IN OUT UINTN *CommBufferSize OPTIONAL
232 )
233 {
234 EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;
235
236 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));
237
238 LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);
239
240 LockBoxParameterHeader->ReturnStatus = (UINT64)-1;
241
242 DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));
243
244 DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));
245
246 switch (LockBoxParameterHeader->Command) {
247 case EFI_SMM_LOCK_BOX_COMMAND_SAVE:
248 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);
249 break;
250 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:
251 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);
252 break;
253 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:
254 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);
255 break;
256 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:
257 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);
258 break;
259 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:
260 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);
261 break;
262 default:
263 break;
264 }
265
266 LockBoxParameterHeader->Command = (UINT32)-1;
267
268 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n"));
269
270 return EFI_SUCCESS;
271 }
272
273 /**
274 Smm Ready To Lock event notification handler.
275
276 It sets a flag indicating that SMRAM has been locked.
277
278 @param[in] Protocol Points to the protocol's unique identifier.
279 @param[in] Interface Points to the interface instance.
280 @param[in] Handle The handle on which the interface was installed.
281
282 @retval EFI_SUCCESS Notification handler runs successfully.
283 **/
284 EFI_STATUS
285 EFIAPI
286 SmmReadyToLockEventNotify (
287 IN CONST EFI_GUID *Protocol,
288 IN VOID *Interface,
289 IN EFI_HANDLE Handle
290 )
291 {
292 mLocked = TRUE;
293 return EFI_SUCCESS;
294 }
295
296 /**
297 Entry Point for LockBox SMM driver.
298
299 @param[in] ImageHandle Image handle of this driver.
300 @param[in] SystemTable A Pointer to the EFI System Table.
301
302 @retval EFI_SUCEESS
303 @return Others Some error occurs.
304 **/
305 EFI_STATUS
306 EFIAPI
307 SmmLockBoxEntryPoint (
308 IN EFI_HANDLE ImageHandle,
309 IN EFI_SYSTEM_TABLE *SystemTable
310 )
311 {
312 EFI_STATUS Status;
313 EFI_HANDLE DispatchHandle;
314 VOID *Registration;
315 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
316 UINTN Size;
317
318 //
319 // Get SMRAM information
320 //
321 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
322 ASSERT_EFI_ERROR (Status);
323
324 Size = 0;
325 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
326 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
327
328 Status = gSmst->SmmAllocatePool (
329 EfiRuntimeServicesData,
330 Size,
331 (VOID **)&mSmramRanges
332 );
333 ASSERT_EFI_ERROR (Status);
334
335 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
336 ASSERT_EFI_ERROR (Status);
337
338 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
339
340 //
341 // Register LockBox communication handler
342 //
343 Status = gSmst->SmiHandlerRegister (
344 SmmLockBoxHandler,
345 &gEfiSmmLockBoxCommunicationGuid,
346 &DispatchHandle
347 );
348 ASSERT_EFI_ERROR (Status);
349
350 //
351 // Register SMM Ready To Lock Protocol notification
352 //
353 Status = gSmst->SmmRegisterProtocolNotify (
354 &gEfiSmmReadyToLockProtocolGuid,
355 SmmReadyToLockEventNotify,
356 &Registration
357 );
358 ASSERT_EFI_ERROR (Status);
359
360 //
361 // Install NULL to DXE data base as notify
362 //
363 ImageHandle = NULL;
364 Status = gBS->InstallProtocolInterface (
365 &ImageHandle,
366 &gEfiLockBoxProtocolGuid,
367 EFI_NATIVE_INTERFACE,
368 NULL
369 );
370 ASSERT_EFI_ERROR (Status);
371
372 return Status;
373 }