3 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5 Caution: This module requires additional review when modified.
6 This driver will have external input - communicate buffer in SMM mode.
7 This external input must be validated carefully to avoid security issue like
8 buffer overflow, integer overflow.
10 SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()
11 will receive untrusted input and do basic validation.
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions
15 of the BSD License which accompanies this distribution. The
16 full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include <Library/UefiDriverEntryPoint.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <Library/UefiRuntimeServicesTableLib.h>
28 #include <Library/SmmServicesTableLib.h>
29 #include <Library/BaseLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/LockBoxLib.h>
33 #include <Protocol/SmmReadyToLock.h>
34 #include <Protocol/SmmCommunication.h>
35 #include <Protocol/SmmAccess2.h>
36 #include <Protocol/LockBox.h>
37 #include <Guid/SmmLockBox.h>
39 BOOLEAN mLocked
= FALSE
;
41 EFI_SMRAM_DESCRIPTOR
*mSmramRanges
;
42 UINTN mSmramRangeCount
;
45 This function check if the address is in SMRAM.
47 @param Buffer the buffer address to be checked.
48 @param Length the buffer length to be checked.
50 @retval TRUE this address is in SMRAM.
51 @retval FALSE this address is NOT in SMRAM.
55 IN EFI_PHYSICAL_ADDRESS Buffer
,
61 for (Index
= 0; Index
< mSmramRangeCount
; Index
++) {
62 if (((Buffer
>= mSmramRanges
[Index
].CpuStart
) && (Buffer
< mSmramRanges
[Index
].CpuStart
+ mSmramRanges
[Index
].PhysicalSize
)) ||
63 ((mSmramRanges
[Index
].CpuStart
>= Buffer
) && (mSmramRanges
[Index
].CpuStart
< Buffer
+ Length
))) {
72 This function check if the address refered by Buffer and Length is valid.
74 @param Buffer the buffer address to be checked.
75 @param Length the buffer length to be checked.
77 @retval TRUE this address is valid.
78 @retval FALSE this address is NOT valid.
86 if (Buffer
> (MAX_ADDRESS
- Length
)) {
92 if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS
)Buffer
, (UINT64
)Length
)) {
99 Dispatch function for SMM lock box save.
101 Caution: This function may receive untrusted input.
102 Restore buffer and length are external input, so this function will validate
105 @param LockBoxParameterSave parameter of lock box save
109 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*LockBoxParameterSave
118 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
119 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
126 if (!IsAddressValid ((UINTN
)LockBoxParameterSave
->Buffer
, (UINTN
)LockBoxParameterSave
->Length
)) {
127 DEBUG ((EFI_D_ERROR
, "SmmLockBox Save address in SMRAM!\n"));
128 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
135 Status
= SaveLockBox (
136 &LockBoxParameterSave
->Guid
,
137 (VOID
*)(UINTN
)LockBoxParameterSave
->Buffer
,
138 (UINTN
)LockBoxParameterSave
->Length
140 LockBoxParameterSave
->Header
.ReturnStatus
= (UINT64
)Status
;
145 Dispatch function for SMM lock box set attributes.
147 @param LockBoxParameterSetAttributes parameter of lock box set attributes
150 SmmLockBoxSetAttributes (
151 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*LockBoxParameterSetAttributes
160 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
161 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
168 Status
= SetLockBoxAttributes (
169 &LockBoxParameterSetAttributes
->Guid
,
170 LockBoxParameterSetAttributes
->Attributes
172 LockBoxParameterSetAttributes
->Header
.ReturnStatus
= (UINT64
)Status
;
177 Dispatch function for SMM lock box update.
179 Caution: This function may receive untrusted input.
180 Restore buffer and length are external input, so this function will validate
183 @param LockBoxParameterUpdate parameter of lock box update
187 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*LockBoxParameterUpdate
196 DEBUG ((EFI_D_ERROR
, "SmmLockBox Locked!\n"));
197 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
204 if (!IsAddressValid ((UINTN
)LockBoxParameterUpdate
->Buffer
, (UINTN
)LockBoxParameterUpdate
->Length
)) {
205 DEBUG ((EFI_D_ERROR
, "SmmLockBox Update address in SMRAM!\n"));
206 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
213 Status
= UpdateLockBox (
214 &LockBoxParameterUpdate
->Guid
,
215 (UINTN
)LockBoxParameterUpdate
->Offset
,
216 (VOID
*)(UINTN
)LockBoxParameterUpdate
->Buffer
,
217 (UINTN
)LockBoxParameterUpdate
->Length
219 LockBoxParameterUpdate
->Header
.ReturnStatus
= (UINT64
)Status
;
224 Dispatch function for SMM lock box restore.
226 Caution: This function may receive untrusted input.
227 Restore buffer and length are external input, so this function will validate
230 @param LockBoxParameterRestore parameter of lock box restore
234 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*LockBoxParameterRestore
242 if (!IsAddressValid ((UINTN
)LockBoxParameterRestore
->Buffer
, (UINTN
)LockBoxParameterRestore
->Length
)) {
243 DEBUG ((EFI_D_ERROR
, "SmmLockBox Restore address in SMRAM!\n"));
244 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)EFI_ACCESS_DENIED
;
251 if ((LockBoxParameterRestore
->Length
== 0) && (LockBoxParameterRestore
->Buffer
== 0)) {
252 Status
= RestoreLockBox (
253 &LockBoxParameterRestore
->Guid
,
258 Status
= RestoreLockBox (
259 &LockBoxParameterRestore
->Guid
,
260 (VOID
*)(UINTN
)LockBoxParameterRestore
->Buffer
,
261 (UINTN
*)&LockBoxParameterRestore
->Length
264 LockBoxParameterRestore
->Header
.ReturnStatus
= (UINT64
)Status
;
269 Dispatch function for SMM lock box restore all in place.
271 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place
274 SmmLockBoxRestoreAllInPlace (
275 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*LockBoxParameterRestoreAllInPlace
280 Status
= RestoreAllLockBoxInPlace ();
281 LockBoxParameterRestoreAllInPlace
->Header
.ReturnStatus
= (UINT64
)Status
;
286 Dispatch function for a Software SMI handler.
288 Caution: This function may receive untrusted input.
289 Communicate buffer and buffer size are external input, so this function will do basic validation.
291 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
292 @param Context Points to an optional handler context which was specified when the
293 handler was registered.
294 @param CommBuffer A pointer to a collection of data in memory that will
295 be conveyed from a non-SMM environment into an SMM environment.
296 @param CommBufferSize The size of the CommBuffer.
298 @retval EFI_SUCCESS Command is handled successfully.
304 IN EFI_HANDLE DispatchHandle
,
305 IN CONST VOID
*Context OPTIONAL
,
306 IN OUT VOID
*CommBuffer OPTIONAL
,
307 IN OUT UINTN
*CommBufferSize OPTIONAL
310 EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*LockBoxParameterHeader
;
312 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Enter\n"));
317 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER
)) {
318 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size invalid!\n"));
321 if (!IsAddressValid ((UINTN
)CommBuffer
, *CommBufferSize
)) {
322 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer in SMRAM!\n"));
326 LockBoxParameterHeader
= (EFI_SMM_LOCK_BOX_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
328 LockBoxParameterHeader
->ReturnStatus
= (UINT64
)-1;
330 DEBUG ((EFI_D_ERROR
, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN
)LockBoxParameterHeader
));
332 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command - %x\n", (UINTN
)LockBoxParameterHeader
->Command
));
334 switch (LockBoxParameterHeader
->Command
) {
335 case EFI_SMM_LOCK_BOX_COMMAND_SAVE
:
336 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE
)) {
337 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
340 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE
*)(UINTN
)LockBoxParameterHeader
);
342 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE
:
343 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
)) {
344 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
347 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE
*)(UINTN
)LockBoxParameterHeader
);
349 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE
:
350 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
)) {
351 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
354 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE
*)(UINTN
)LockBoxParameterHeader
);
356 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES
:
357 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
)) {
358 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
361 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES
*)(UINTN
)LockBoxParameterHeader
);
363 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE
:
364 if (*CommBufferSize
< sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
)) {
365 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
368 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE
*)(UINTN
)LockBoxParameterHeader
);
371 DEBUG ((EFI_D_ERROR
, "SmmLockBox Command invalid!\n"));
375 LockBoxParameterHeader
->Command
= (UINT32
)-1;
377 DEBUG ((EFI_D_ERROR
, "SmmLockBox SmmLockBoxHandler Exit\n"));
383 Smm Ready To Lock event notification handler.
385 It sets a flag indicating that SMRAM has been locked.
387 @param[in] Protocol Points to the protocol's unique identifier.
388 @param[in] Interface Points to the interface instance.
389 @param[in] Handle The handle on which the interface was installed.
391 @retval EFI_SUCCESS Notification handler runs successfully.
395 SmmReadyToLockEventNotify (
396 IN CONST EFI_GUID
*Protocol
,
406 Entry Point for LockBox SMM driver.
408 @param[in] ImageHandle Image handle of this driver.
409 @param[in] SystemTable A Pointer to the EFI System Table.
412 @return Others Some error occurs.
416 SmmLockBoxEntryPoint (
417 IN EFI_HANDLE ImageHandle
,
418 IN EFI_SYSTEM_TABLE
*SystemTable
422 EFI_HANDLE DispatchHandle
;
424 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
428 // Get SMRAM information
430 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**)&SmmAccess
);
431 ASSERT_EFI_ERROR (Status
);
434 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, NULL
);
435 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
437 Status
= gSmst
->SmmAllocatePool (
438 EfiRuntimeServicesData
,
440 (VOID
**)&mSmramRanges
442 ASSERT_EFI_ERROR (Status
);
444 Status
= SmmAccess
->GetCapabilities (SmmAccess
, &Size
, mSmramRanges
);
445 ASSERT_EFI_ERROR (Status
);
447 mSmramRangeCount
= Size
/ sizeof (EFI_SMRAM_DESCRIPTOR
);
450 // Register LockBox communication handler
452 Status
= gSmst
->SmiHandlerRegister (
454 &gEfiSmmLockBoxCommunicationGuid
,
457 ASSERT_EFI_ERROR (Status
);
460 // Register SMM Ready To Lock Protocol notification
462 Status
= gSmst
->SmmRegisterProtocolNotify (
463 &gEfiSmmReadyToLockProtocolGuid
,
464 SmmReadyToLockEventNotify
,
467 ASSERT_EFI_ERROR (Status
);
470 // Install NULL to DXE data base as notify
473 Status
= gBS
->InstallProtocolInterface (
475 &gEfiLockBoxProtocolGuid
,
476 EFI_NATIVE_INTERFACE
,
479 ASSERT_EFI_ERROR (Status
);