4 Caution: This module requires additional review when modified.
5 This driver will have external input - communicate buffer in SMM mode.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
9 SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()
10 will receive untrusted input and do basic validation.
12 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions
16 of the BSD License which accompanies this distribution. The
17 full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 #include <Library/UefiDriverEntryPoint.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/UefiRuntimeServicesTableLib.h>
29 #include <Library/SmmServicesTableLib.h>
30 #include <Library/BaseLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/LockBoxLib.h>
34 #include <Protocol/SmmReadyToLock.h>
35 #include <Protocol/SmmCommunication.h>
36 #include <Protocol/SmmAccess2.h>
37 #include <Protocol/LockBox.h>
38 #include <Guid/SmmLockBox.h>
40 BOOLEAN mLocked
= FALSE
;
42 EFI_SMRAM_DESCRIPTOR
*mSmramRanges
;
43 UINTN mSmramRangeCount
;
46 This function check if the address is in SMRAM.
48 @param Buffer the buffer address to be checked.
49 @param Length the buffer length to be checked.
51 @retval TRUE this address is in SMRAM.
52 @retval FALSE this address is NOT in SMRAM.
56 IN EFI_PHYSICAL_ADDRESS Buffer
,
62 for (Index
= 0; Index
< mSmramRangeCount
; Index
++) {
63 if (((Buffer
>= mSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmramRanges
[Index
].CpuStart
+ mSmramRanges
[Index
].PhysicalSize
)) ||
64 ((mSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
73 This function check if the address refered by Buffer and Length is valid.
75 @param Buffer the buffer address to be checked.
76 @param Length the buffer length to be checked.
78 @retval TRUE this address is valid.
79 @retval FALSE this address is NOT valid.
87 if (Buffer
> (MAX_ADDRESS
- Length
)) {
93 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)Buffer
, (UINT64
)Length
)) {
100 Dispatch function for SMM lock box save.
102 Caution: This function may receive untrusted input.
103 Restore buffer and length are external input, so this function will validate
106 @param LockBoxParameterSave parameter of lock box save
110 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*LockBoxParameterSave
119 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
120 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
127 if (!IsAddressValid ((UINTN
)LockBoxParameterSave
->Buffer
, (UINTN
)LockBoxParameterSave
->Length
)) {
128 DEBUG ((EFI_D_ERROR
, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));
129 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
136 Status
= SaveLockBox (
137 &LockBoxParameterSave
->Guid
,
138 (VOID
*)(UINTN
)LockBoxParameterSave
->Buffer
,
139 (UINTN
)LockBoxParameterSave
->Length
141 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)Status
;
146 Dispatch function for SMM lock box set attributes.
148 @param LockBoxParameterSetAttributes parameter of lock box set attributes
151 SmmLockBoxSetAttributes (
152 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*LockBoxParameterSetAttributes
161 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
162 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
169 Status
= SetLockBoxAttributes (
170 &LockBoxParameterSetAttributes
->Guid
,
171 LockBoxParameterSetAttributes
->Attributes
173 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)Status
;
178 Dispatch function for SMM lock box update.
180 Caution: This function may receive untrusted input.
181 Restore buffer and length are external input, so this function will validate
184 @param LockBoxParameterUpdate parameter of lock box update
188 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*LockBoxParameterUpdate
197 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
198 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
205 if (!IsAddressValid ((UINTN
)LockBoxParameterUpdate
->Buffer
, (UINTN
)LockBoxParameterUpdate
->Length
)) {
206 DEBUG ((EFI_D_ERROR
, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));
207 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
214 Status
= UpdateLockBox (
215 &LockBoxParameterUpdate
->Guid
,
216 (UINTN
)LockBoxParameterUpdate
->Offset
,
217 (VOID
*)(UINTN
)LockBoxParameterUpdate
->Buffer
,
218 (UINTN
)LockBoxParameterUpdate
->Length
220 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)Status
;
225 Dispatch function for SMM lock box restore.
227 Caution: This function may receive untrusted input.
228 Restore buffer and length are external input, so this function will validate
231 @param LockBoxParameterRestore parameter of lock box restore
235 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*LockBoxParameterRestore
243 if (!IsAddressValid ((UINTN
)LockBoxParameterRestore
->Buffer
, (UINTN
)LockBoxParameterRestore
->Length
)) {
244 DEBUG ((EFI_D_ERROR
, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));
245 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
252 if ((LockBoxParameterRestore
->Length
== 0) && (LockBoxParameterRestore
->Buffer
== 0)) {
253 Status
= RestoreLockBox (
254 &LockBoxParameterRestore
->Guid
,
259 Status
= RestoreLockBox (
260 &LockBoxParameterRestore
->Guid
,
261 (VOID
*)(UINTN
)LockBoxParameterRestore
->Buffer
,
262 (UINTN
*)&LockBoxParameterRestore
->Length
265 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)Status
;
270 Dispatch function for SMM lock box restore all in place.
272 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
275 SmmLockBoxRestoreAllInPlace (
276 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*LockBoxParameterRestoreAllInPlace
281 Status
= RestoreAllLockBoxInPlace ();
282 LockBoxParameterRestoreAllInPlace
->Header
.ReturnStatus
= (UINT64
)Status
;
287 Dispatch function for a Software SMI handler.
289 Caution: This function may receive untrusted input.
290 Communicate buffer and buffer size are external input, so this function will do basic validation.
292 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
293 @param Context Points to an optional handler context which was specified when the
294 handler was registered.
295 @param CommBuffer A pointer to a collection of data in memory that will
296 be conveyed from a non-SMM environment into an SMM environment.
297 @param CommBufferSize The size of the CommBuffer.
299 @retval EFI_SUCCESS Command is handled successfully.
305 IN EFI_HANDLE DispatchHandle
,
306 IN CONST VOID
*Context OPTIONAL
,
307 IN OUT VOID
*CommBuffer OPTIONAL
,
308 IN OUT UINTN
*CommBufferSize OPTIONAL
311 EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*LockBoxParameterHeader
;
313 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Enter\n"));
318 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER
)) {
319 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size invalid!\n"));
322 if (!IsAddressValid ((UINTN
)CommBuffer
, *CommBufferSize
)) {
323 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));
327 LockBoxParameterHeader
= (EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
329 LockBoxParameterHeader
->ReturnStatus
= (UINT64
)-1;
331 DEBUG ((EFI_D_ERROR
, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN
)LockBoxParameterHeader
));
333 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command - %x\n", (UINTN
)LockBoxParameterHeader
->Command
));
335 switch (LockBoxParameterHeader
->Command
) {
336 case EFI_SMM_LOCK_BOX_COMMAND_SAVE
:
337 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE
)) {
338 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
341 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*)(UINTN
)LockBoxParameterHeader
);
343 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE
:
344 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
)) {
345 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
348 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*)(UINTN
)LockBoxParameterHeader
);
350 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE
:
351 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
)) {
352 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
355 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*)(UINTN
)LockBoxParameterHeader
);
357 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES
:
358 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
)) {
359 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
362 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*)(UINTN
)LockBoxParameterHeader
);
364 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE
:
365 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
)) {
366 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
369 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*)(UINTN
)LockBoxParameterHeader
);
372 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command invalid!\n"));
376 LockBoxParameterHeader
->Command
= (UINT32
)-1;
378 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Exit\n"));
384 Smm Ready To Lock event notification handler.
386 It sets a flag indicating that SMRAM has been locked.
388 @param[in] Protocol Points to the protocol's unique identifier.
389 @param[in] Interface Points to the interface instance.
390 @param[in] Handle The handle on which the interface was installed.
392 @retval EFI_SUCCESS Notification handler runs successfully.
396 SmmReadyToLockEventNotify (
397 IN CONST EFI_GUID
*Protocol
,
407 Entry Point for LockBox SMM driver.
409 @param[in] ImageHandle Image handle of this driver.
410 @param[in] SystemTable A Pointer to the EFI System Table.
413 @return Others Some error occurs.
417 SmmLockBoxEntryPoint (
418 IN EFI_HANDLE ImageHandle
,
419 IN EFI_SYSTEM_TABLE
*SystemTable
423 EFI_HANDLE DispatchHandle
;
425 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
429 // Get SMRAM information
431 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
432 ASSERT_EFI_ERROR (Status
);
435 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
436 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
438 Status
= gSmst
->SmmAllocatePool (
439 EfiRuntimeServicesData
,
441 (VOID
**)&mSmramRanges
443 ASSERT_EFI_ERROR (Status
);
445 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
446 ASSERT_EFI_ERROR (Status
);
448 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
451 // Register LockBox communication handler
453 Status
= gSmst
->SmiHandlerRegister (
455 &gEfiSmmLockBoxCommunicationGuid
,
458 ASSERT_EFI_ERROR (Status
);
461 // Register SMM Ready To Lock Protocol notification
463 Status
= gSmst
->SmmRegisterProtocolNotify (
464 &gEfiSmmReadyToLockProtocolGuid
,
465 SmmReadyToLockEventNotify
,
468 ASSERT_EFI_ERROR (Status
);
471 // Install NULL to DXE data base as notify
474 Status
= gBS
->InstallProtocolInterface (
476 &gEfiLockBoxProtocolGuid
,
477 EFI_NATIVE_INTERFACE
,
480 ASSERT_EFI_ERROR (Status
);