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
114 EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave
;
120 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
121 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
125 CopyMem (&TempLockBoxParameterSave
, LockBoxParameterSave
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE
));
130 if (!IsAddressValid ((UINTN
)TempLockBoxParameterSave
.Buffer
, (UINTN
)TempLockBoxParameterSave
.Length
)) {
131 DEBUG ((EFI_D_ERROR
, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));
132 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
139 Status
= SaveLockBox (
140 &TempLockBoxParameterSave
.Guid
,
141 (VOID
*)(UINTN
)TempLockBoxParameterSave
.Buffer
,
142 (UINTN
)TempLockBoxParameterSave
.Length
144 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)Status
;
149 Dispatch function for SMM lock box set attributes.
151 @param LockBoxParameterSetAttributes parameter of lock box set attributes
154 SmmLockBoxSetAttributes (
155 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*LockBoxParameterSetAttributes
159 EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes
;
165 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
166 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
170 CopyMem (&TempLockBoxParameterSetAttributes
, LockBoxParameterSetAttributes
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
));
175 Status
= SetLockBoxAttributes (
176 &TempLockBoxParameterSetAttributes
.Guid
,
177 TempLockBoxParameterSetAttributes
.Attributes
179 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)Status
;
184 Dispatch function for SMM lock box update.
186 Caution: This function may receive untrusted input.
187 Restore buffer and length are external input, so this function will validate
190 @param LockBoxParameterUpdate parameter of lock box update
194 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*LockBoxParameterUpdate
198 EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate
;
204 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
205 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
209 CopyMem (&TempLockBoxParameterUpdate
, LockBoxParameterUpdate
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
));
214 if (!IsAddressValid ((UINTN
)TempLockBoxParameterUpdate
.Buffer
, (UINTN
)TempLockBoxParameterUpdate
.Length
)) {
215 DEBUG ((EFI_D_ERROR
, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));
216 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
223 Status
= UpdateLockBox (
224 &TempLockBoxParameterUpdate
.Guid
,
225 (UINTN
)TempLockBoxParameterUpdate
.Offset
,
226 (VOID
*)(UINTN
)TempLockBoxParameterUpdate
.Buffer
,
227 (UINTN
)TempLockBoxParameterUpdate
.Length
229 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)Status
;
234 Dispatch function for SMM lock box restore.
236 Caution: This function may receive untrusted input.
237 Restore buffer and length are external input, so this function will validate
240 @param LockBoxParameterRestore parameter of lock box restore
244 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*LockBoxParameterRestore
248 EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore
;
250 CopyMem (&TempLockBoxParameterRestore
, LockBoxParameterRestore
, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
));
255 if (!IsAddressValid ((UINTN
)TempLockBoxParameterRestore
.Buffer
, (UINTN
)TempLockBoxParameterRestore
.Length
)) {
256 DEBUG ((EFI_D_ERROR
, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));
257 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
264 if ((TempLockBoxParameterRestore
.Length
== 0) && (TempLockBoxParameterRestore
.Buffer
== 0)) {
265 Status
= RestoreLockBox (
266 &TempLockBoxParameterRestore
.Guid
,
271 Status
= RestoreLockBox (
272 &TempLockBoxParameterRestore
.Guid
,
273 (VOID
*)(UINTN
)TempLockBoxParameterRestore
.Buffer
,
274 (UINTN
*)&TempLockBoxParameterRestore
.Length
277 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)Status
;
282 Dispatch function for SMM lock box restore all in place.
284 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
287 SmmLockBoxRestoreAllInPlace (
288 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*LockBoxParameterRestoreAllInPlace
293 Status
= RestoreAllLockBoxInPlace ();
294 LockBoxParameterRestoreAllInPlace
->Header
.ReturnStatus
= (UINT64
)Status
;
299 Dispatch function for a Software SMI handler.
301 Caution: This function may receive untrusted input.
302 Communicate buffer and buffer size are external input, so this function will do basic validation.
304 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
305 @param Context Points to an optional handler context which was specified when the
306 handler was registered.
307 @param CommBuffer A pointer to a collection of data in memory that will
308 be conveyed from a non-SMM environment into an SMM environment.
309 @param CommBufferSize The size of the CommBuffer.
311 @retval EFI_SUCCESS Command is handled successfully.
317 IN EFI_HANDLE DispatchHandle
,
318 IN CONST VOID
*Context OPTIONAL
,
319 IN OUT VOID
*CommBuffer OPTIONAL
,
320 IN OUT UINTN
*CommBufferSize OPTIONAL
323 EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*LockBoxParameterHeader
;
324 UINTN TempCommBufferSize
;
326 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Enter\n"));
329 // If input is invalid, stop processing this SMI
331 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
335 TempCommBufferSize
= *CommBufferSize
;
340 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER
)) {
341 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size invalid!\n"));
344 if (!IsAddressValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
345 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));
349 LockBoxParameterHeader
= (EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
351 LockBoxParameterHeader
->ReturnStatus
= (UINT64
)-1;
353 DEBUG ((EFI_D_ERROR
, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN
)LockBoxParameterHeader
));
355 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command - %x\n", (UINTN
)LockBoxParameterHeader
->Command
));
357 switch (LockBoxParameterHeader
->Command
) {
358 case EFI_SMM_LOCK_BOX_COMMAND_SAVE
:
359 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE
)) {
360 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
363 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*)(UINTN
)LockBoxParameterHeader
);
365 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE
:
366 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
)) {
367 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
370 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*)(UINTN
)LockBoxParameterHeader
);
372 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE
:
373 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
)) {
374 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
377 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*)(UINTN
)LockBoxParameterHeader
);
379 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES
:
380 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
)) {
381 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
384 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*)(UINTN
)LockBoxParameterHeader
);
386 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE
:
387 if (TempCommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
)) {
388 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
391 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*)(UINTN
)LockBoxParameterHeader
);
394 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command invalid!\n"));
398 LockBoxParameterHeader
->Command
= (UINT32
)-1;
400 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Exit\n"));
406 Smm Ready To Lock event notification handler.
408 It sets a flag indicating that SMRAM has been locked.
410 @param[in] Protocol Points to the protocol's unique identifier.
411 @param[in] Interface Points to the interface instance.
412 @param[in] Handle The handle on which the interface was installed.
414 @retval EFI_SUCCESS Notification handler runs successfully.
418 SmmReadyToLockEventNotify (
419 IN CONST EFI_GUID
*Protocol
,
429 Entry Point for LockBox SMM driver.
431 @param[in] ImageHandle Image handle of this driver.
432 @param[in] SystemTable A Pointer to the EFI System Table.
435 @return Others Some error occurs.
439 SmmLockBoxEntryPoint (
440 IN EFI_HANDLE ImageHandle
,
441 IN EFI_SYSTEM_TABLE
*SystemTable
445 EFI_HANDLE DispatchHandle
;
447 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
451 // Get SMRAM information
453 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
454 ASSERT_EFI_ERROR (Status
);
457 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
458 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
460 Status
= gSmst
->SmmAllocatePool (
461 EfiRuntimeServicesData
,
463 (VOID
**)&mSmramRanges
465 ASSERT_EFI_ERROR (Status
);
467 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
468 ASSERT_EFI_ERROR (Status
);
470 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
473 // Register LockBox communication handler
475 Status
= gSmst
->SmiHandlerRegister (
477 &gEfiSmmLockBoxCommunicationGuid
,
480 ASSERT_EFI_ERROR (Status
);
483 // Register SMM Ready To Lock Protocol notification
485 Status
= gSmst
->SmmRegisterProtocolNotify (
486 &gEfiSmmReadyToLockProtocolGuid
,
487 SmmReadyToLockEventNotify
,
490 ASSERT_EFI_ERROR (Status
);
493 // Install NULL to DXE data base as notify
496 Status
= gBS
->InstallProtocolInterface (
498 &gEfiLockBoxProtocolGuid
,
499 EFI_NATIVE_INTERFACE
,
502 ASSERT_EFI_ERROR (Status
);