]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
RestoreLockBox in DXE with Length NULL, Buffer NULL will fail to get data from Lockbo...
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
1 /** @file
2
3 Copyright (c) 2010 - 2011, 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 if ((LockBoxParameterRestore->Length == 0) && (LockBoxParameterRestore->Buffer == 0)) {
187 Status = RestoreLockBox (
188 &LockBoxParameterRestore->Guid,
189 NULL,
190 NULL
191 );
192 } else {
193 Status = RestoreLockBox (
194 &LockBoxParameterRestore->Guid,
195 (VOID *)(UINTN)LockBoxParameterRestore->Buffer,
196 (UINTN *)&LockBoxParameterRestore->Length
197 );
198 }
199 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
200 return ;
201 }
202
203 /**
204 Dispatch function for SMM lock box restore all in place.
205
206 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
207 **/
208 VOID
209 SmmLockBoxRestoreAllInPlace (
210 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace
211 )
212 {
213 EFI_STATUS Status;
214
215 Status = RestoreAllLockBoxInPlace ();
216 LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;
217 return ;
218 }
219
220 /**
221 Dispatch function for a Software SMI handler.
222
223 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
224 @param Context Points to an optional handler context which was specified when the
225 handler was registered.
226 @param CommBuffer A pointer to a collection of data in memory that will
227 be conveyed from a non-SMM environment into an SMM environment.
228 @param CommBufferSize The size of the CommBuffer.
229
230 @retval EFI_SUCCESS Command is handled successfully.
231
232 **/
233 EFI_STATUS
234 EFIAPI
235 SmmLockBoxHandler (
236 IN EFI_HANDLE DispatchHandle,
237 IN CONST VOID *Context OPTIONAL,
238 IN OUT VOID *CommBuffer OPTIONAL,
239 IN OUT UINTN *CommBufferSize OPTIONAL
240 )
241 {
242 EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;
243
244 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));
245
246 LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);
247
248 LockBoxParameterHeader->ReturnStatus = (UINT64)-1;
249
250 DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));
251
252 DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));
253
254 switch (LockBoxParameterHeader->Command) {
255 case EFI_SMM_LOCK_BOX_COMMAND_SAVE:
256 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);
257 break;
258 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:
259 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);
260 break;
261 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:
262 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);
263 break;
264 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:
265 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);
266 break;
267 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:
268 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);
269 break;
270 default:
271 break;
272 }
273
274 LockBoxParameterHeader->Command = (UINT32)-1;
275
276 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n"));
277
278 return EFI_SUCCESS;
279 }
280
281 /**
282 Smm Ready To Lock event notification handler.
283
284 It sets a flag indicating that SMRAM has been locked.
285
286 @param[in] Protocol Points to the protocol's unique identifier.
287 @param[in] Interface Points to the interface instance.
288 @param[in] Handle The handle on which the interface was installed.
289
290 @retval EFI_SUCCESS Notification handler runs successfully.
291 **/
292 EFI_STATUS
293 EFIAPI
294 SmmReadyToLockEventNotify (
295 IN CONST EFI_GUID *Protocol,
296 IN VOID *Interface,
297 IN EFI_HANDLE Handle
298 )
299 {
300 mLocked = TRUE;
301 return EFI_SUCCESS;
302 }
303
304 /**
305 Entry Point for LockBox SMM driver.
306
307 @param[in] ImageHandle Image handle of this driver.
308 @param[in] SystemTable A Pointer to the EFI System Table.
309
310 @retval EFI_SUCEESS
311 @return Others Some error occurs.
312 **/
313 EFI_STATUS
314 EFIAPI
315 SmmLockBoxEntryPoint (
316 IN EFI_HANDLE ImageHandle,
317 IN EFI_SYSTEM_TABLE *SystemTable
318 )
319 {
320 EFI_STATUS Status;
321 EFI_HANDLE DispatchHandle;
322 VOID *Registration;
323 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
324 UINTN Size;
325
326 //
327 // Get SMRAM information
328 //
329 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
330 ASSERT_EFI_ERROR (Status);
331
332 Size = 0;
333 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
334 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
335
336 Status = gSmst->SmmAllocatePool (
337 EfiRuntimeServicesData,
338 Size,
339 (VOID **)&mSmramRanges
340 );
341 ASSERT_EFI_ERROR (Status);
342
343 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
344 ASSERT_EFI_ERROR (Status);
345
346 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
347
348 //
349 // Register LockBox communication handler
350 //
351 Status = gSmst->SmiHandlerRegister (
352 SmmLockBoxHandler,
353 &gEfiSmmLockBoxCommunicationGuid,
354 &DispatchHandle
355 );
356 ASSERT_EFI_ERROR (Status);
357
358 //
359 // Register SMM Ready To Lock Protocol notification
360 //
361 Status = gSmst->SmmRegisterProtocolNotify (
362 &gEfiSmmReadyToLockProtocolGuid,
363 SmmReadyToLockEventNotify,
364 &Registration
365 );
366 ASSERT_EFI_ERROR (Status);
367
368 //
369 // Install NULL to DXE data base as notify
370 //
371 ImageHandle = NULL;
372 Status = gBS->InstallProtocolInterface (
373 &ImageHandle,
374 &gEfiLockBoxProtocolGuid,
375 EFI_NATIVE_INTERFACE,
376 NULL
377 );
378 ASSERT_EFI_ERROR (Status);
379
380 return Status;
381 }