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