From 1c837cd545b6b91c41f1fbebf84b54cb7ccf499e Mon Sep 17 00:00:00 2001 From: jljusten Date: Tue, 19 Jul 2011 20:47:28 +0000 Subject: [PATCH] MdeModulePkg: Add SMM LockBox This includes: * LockBox protocol definition * LockBoxLib library interface definition * SmmLockBox GUID * LockBoxNullLib library implementation * 2 SmmLockBoxLib library implementations * SmmLockBox SMM driver Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a Reviewed-by: jyao1 Reviewed-by: lgao4 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12029 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Include/Guid/SmmLockBox.h | 73 +++ MdeModulePkg/Include/Library/LockBoxLib.h | 133 +++++ MdeModulePkg/Include/Protocol/LockBox.h | 31 + .../Library/LockBoxNullLib/LockBoxNullLib.c | 139 +++++ .../Library/LockBoxNullLib/LockBoxNullLib.inf | 41 ++ .../Library/SmmLockBoxLib/SmmLockBoxDxeLib.c | 455 +++++++++++++++ .../SmmLockBoxLib/SmmLockBoxDxeLib.inf | 50 ++ .../SmmLockBoxLib/SmmLockBoxLibPrivate.h | 54 ++ .../Library/SmmLockBoxLib/SmmLockBoxSmmLib.c | 542 ++++++++++++++++++ .../SmmLockBoxLib/SmmLockBoxSmmLib.inf | 46 ++ MdeModulePkg/MdeModulePkg.dec | 7 + MdeModulePkg/MdeModulePkg.dsc | 7 + .../Universal/LockBox/SmmLockBox/SmmLockBox.c | 373 ++++++++++++ .../LockBox/SmmLockBox/SmmLockBox.inf | 59 ++ 14 files changed, 2010 insertions(+) create mode 100644 MdeModulePkg/Include/Guid/SmmLockBox.h create mode 100644 MdeModulePkg/Include/Library/LockBoxLib.h create mode 100644 MdeModulePkg/Include/Protocol/LockBox.h create mode 100644 MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.c create mode 100644 MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf create mode 100644 MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c create mode 100644 MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf diff --git a/MdeModulePkg/Include/Guid/SmmLockBox.h b/MdeModulePkg/Include/Guid/SmmLockBox.h new file mode 100644 index 0000000000..8422847c5a --- /dev/null +++ b/MdeModulePkg/Include/Guid/SmmLockBox.h @@ -0,0 +1,73 @@ +/** @file + SmmLockBox guid header file. + +Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_LOCK_BOX_GUID_H_ +#define _SMM_LOCK_BOX_GUID_H_ + +#define EFI_SMM_LOCK_BOX_COMMUNICATION_GUID \ + {0x2a3cfebd, 0x27e8, 0x4d0a, {0x8b, 0x79, 0xd6, 0x88, 0xc2, 0xa3, 0xe1, 0xc0}} + +// +// Below data structure is used for communication between PEI/DXE to SMM. +// + +#define EFI_SMM_LOCK_BOX_COMMAND_SAVE 0x1 +#define EFI_SMM_LOCK_BOX_COMMAND_UPDATE 0x2 +#define EFI_SMM_LOCK_BOX_COMMAND_RESTORE 0x3 +#define EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES 0x4 +#define EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE 0x5 + +typedef struct { + UINT32 Command; + UINT32 DataLength; + UINT64 ReturnStatus; +} EFI_SMM_LOCK_BOX_PARAMETER_HEADER; + +typedef struct { + EFI_SMM_LOCK_BOX_PARAMETER_HEADER Header; + GUID Guid; + PHYSICAL_ADDRESS Buffer; + UINT64 Length; +} EFI_SMM_LOCK_BOX_PARAMETER_SAVE; + +typedef struct { + EFI_SMM_LOCK_BOX_PARAMETER_HEADER Header; + GUID Guid; + UINT64 Offset; + PHYSICAL_ADDRESS Buffer; + UINT64 Length; +} EFI_SMM_LOCK_BOX_PARAMETER_UPDATE; + +typedef struct { + EFI_SMM_LOCK_BOX_PARAMETER_HEADER Header; + GUID Guid; + PHYSICAL_ADDRESS Buffer; + UINT64 Length; +} EFI_SMM_LOCK_BOX_PARAMETER_RESTORE; + +typedef struct { + EFI_SMM_LOCK_BOX_PARAMETER_HEADER Header; + GUID Guid; + UINT64 Attributes; +} EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES; + +typedef struct { + EFI_SMM_LOCK_BOX_PARAMETER_HEADER Header; +} EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE; + +extern EFI_GUID gEfiSmmLockBoxCommunicationGuid; + +#endif diff --git a/MdeModulePkg/Include/Library/LockBoxLib.h b/MdeModulePkg/Include/Library/LockBoxLib.h new file mode 100644 index 0000000000..db7fd05def --- /dev/null +++ b/MdeModulePkg/Include/Library/LockBoxLib.h @@ -0,0 +1,133 @@ +/** @file + This library is only intended to be used by DXE modules that need save + confidential information to LockBox and get it by PEI modules in S3 phase. + +Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LOCK_BOX_LIB_H_ +#define _LOCK_BOX_LIB_H_ + +/** + This function will save confidential information to lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the confidential information + @param Length the length of the confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0 + @retval RETURN_ALREADY_STARTED the requested GUID already exist. + @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SaveLockBox ( + IN GUID *Guid, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + This function will set lockbox attributes. + + @param Guid the guid to identify the confidential information + @param Attributes the attributes of the lockbox + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER attributes is invalid. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SetLockBoxAttributes ( + IN GUID *Guid, + IN UINT64 Attributes + ); + +// +// With this flag, this LockBox can be restored to this Buffer with RestoreAllLockBoxInPlace() +// +#define LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE BIT0 + +/** + This function will update confidential information to lockbox. + + @param Guid the guid to identify the original confidential information + @param Offset the offset of the original confidential information + @param Buffer the address of the updated confidential information + @param Length the length of the updated confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +UpdateLockBox ( + IN GUID *Guid, + IN UINTN Offset, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + This function will restore confidential information from lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the restored confidential information + NULL means restored to original address, Length MUST be NULL at same time. + @param Length the length of the restored confidential information + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL. + @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no + LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute. + @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_ACCESS_DENIED not allow to restore to the address + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreLockBox ( + IN GUID *Guid, + IN VOID *Buffer, OPTIONAL + IN OUT UINTN *Length OPTIONAL + ); + +/** + This function will restore confidential information from all lockbox which have RestoreInPlace attribute. + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreAllLockBoxInPlace ( + VOID + ); + +#endif diff --git a/MdeModulePkg/Include/Protocol/LockBox.h b/MdeModulePkg/Include/Protocol/LockBox.h new file mode 100644 index 0000000000..a3533c536c --- /dev/null +++ b/MdeModulePkg/Include/Protocol/LockBox.h @@ -0,0 +1,31 @@ +/** @file + LockBox protocol header file. + This is used to resolve dependency problem. The LockBox implementation + install this to broadcast that LockBox API is ready. The driver who will + use LockBox at its ENTRYPOINT should add this dependency. + +Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LOCK_BOX_PROTOCOL_H_ +#define _LOCK_BOX_PROTOCOL_H_ + +/// +/// Global ID for the EFI LOCK BOX Protocol. +/// +#define EFI_LOCK_BOX_PROTOCOL_GUID \ + { 0xbd445d79, 0xb7ad, 0x4f04, { 0x9a, 0xd8, 0x29, 0xbd, 0x20, 0x40, 0xeb, 0x3c }} + +extern EFI_GUID gEfiLockBoxProtocolGuid; + +#endif diff --git a/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.c b/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.c new file mode 100644 index 0000000000..5d7b52c06e --- /dev/null +++ b/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.c @@ -0,0 +1,139 @@ +/** @file + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + This function will save confidential information to lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the confidential information + @param Length the length of the confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0 + @retval RETURN_ALREADY_STARTED the requested GUID already exist. + @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SaveLockBox ( + IN GUID *Guid, + IN VOID *Buffer, + IN UINTN Length + ) +{ + return RETURN_SUCCESS; +} + +/** + This function will set lockbox attributes. + + @param Guid the guid to identify the confidential information + @param Attributes the attributes of the lockbox + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER attributes is invalid. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SetLockBoxAttributes ( + IN GUID *Guid, + IN UINT64 Attributes + ) +{ + return RETURN_SUCCESS; +} + +/** + This function will update confidential information to lockbox. + + @param Guid the guid to identify the original confidential information + @param Offset the offset of the original confidential information + @param Buffer the address of the updated confidential information + @param Length the length of the updated confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +UpdateLockBox ( + IN GUID *Guid, + IN UINTN Offset, + IN VOID *Buffer, + IN UINTN Length + ) +{ + return RETURN_SUCCESS; +} + +/** + This function will restore confidential information from lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the restored confidential information + NULL means restored to original address, Length MUST be NULL at same time. + @param Length the length of the restored confidential information + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL. + @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no + LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute. + @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_ACCESS_DENIED not allow to restore to the address + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreLockBox ( + IN GUID *Guid, + IN VOID *Buffer, OPTIONAL + IN OUT UINTN *Length OPTIONAL + ) +{ + return RETURN_SUCCESS; +} + +/** + This function will restore confidential information from all lockbox which have RestoreInPlace attribute. + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreAllLockBoxInPlace ( + VOID + ) +{ + return RETURN_SUCCESS; +} diff --git a/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf b/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf new file mode 100644 index 0000000000..4665112aef --- /dev/null +++ b/MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf @@ -0,0 +1,41 @@ +## @file +# Component description file for LockBox library. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions +# of the BSD License which accompanies this distribution. The +# full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LockBoxNullLib + FILE_GUID = 0BA38EBD-E190-4df7-8EC4-0A6E2B43772D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = LockBoxLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION DXE_SMM_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + LockBoxNullLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c new file mode 100644 index 0000000000..9659f014e9 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.c @@ -0,0 +1,455 @@ +/** @file + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SmmLockBoxLibPrivate.h" + +/** + This function will save confidential information to lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the confidential information + @param Length the length of the confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0 + @retval RETURN_ALREADY_STARTED the requested GUID already exist. + @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SaveLockBox ( + IN GUID *Guid, + IN VOID *Buffer, + IN UINTN Length + ) +{ + EFI_STATUS Status; + EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; + EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)]; + UINTN CommSize; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SaveLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get needed resource + // + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&SmmCommunication + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + CommHeader->MessageLength = sizeof(*LockBoxParameterSave); + + LockBoxParameterSave = (EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + LockBoxParameterSave->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_SAVE; + LockBoxParameterSave->Header.DataLength = sizeof(*LockBoxParameterSave); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)-1; + CopyMem (&LockBoxParameterSave->Guid, Guid, sizeof(*Guid)); + LockBoxParameterSave->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + LockBoxParameterSave->Length = (UINT64)Length; + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunication->Communicate ( + SmmCommunication, + &CommBuffer[0], + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + Status = (EFI_STATUS)LockBoxParameterSave->Header.ReturnStatus; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SaveLockBox - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + +/** + This function will set lockbox attributes. + + @param Guid the guid to identify the confidential information + @param Attributes the attributes of the lockbox + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER attributes is invalid. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SetLockBoxAttributes ( + IN GUID *Guid, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; + EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)]; + UINTN CommSize; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SetLockBoxAttributes - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || + ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get needed resource + // + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&SmmCommunication + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + CommHeader->MessageLength = sizeof(*LockBoxParameterSetAttributes); + + LockBoxParameterSetAttributes = (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + LockBoxParameterSetAttributes->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES; + LockBoxParameterSetAttributes->Header.DataLength = sizeof(*LockBoxParameterSetAttributes); + LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)-1; + CopyMem (&LockBoxParameterSetAttributes->Guid, Guid, sizeof(*Guid)); + LockBoxParameterSetAttributes->Attributes = (UINT64)Attributes; + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunication->Communicate ( + SmmCommunication, + &CommBuffer[0], + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + Status = (EFI_STATUS)LockBoxParameterSetAttributes->Header.ReturnStatus; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib SetLockBoxAttributes - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + +/** + This function will update confidential information to lockbox. + + @param Guid the guid to identify the original confidential information + @param Offset the offset of the original confidential information + @param Buffer the address of the updated confidential information + @param Length the length of the updated confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +UpdateLockBox ( + IN GUID *Guid, + IN UINTN Offset, + IN VOID *Buffer, + IN UINTN Length + ) +{ + EFI_STATUS Status; + EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; + EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)]; + UINTN CommSize; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib UpdateLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get needed resource + // + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&SmmCommunication + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + CommHeader->MessageLength = sizeof(*LockBoxParameterUpdate); + + LockBoxParameterUpdate = (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + LockBoxParameterUpdate->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_UPDATE; + LockBoxParameterUpdate->Header.DataLength = sizeof(*LockBoxParameterUpdate); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)-1; + CopyMem (&LockBoxParameterUpdate->Guid, Guid, sizeof(*Guid)); + LockBoxParameterUpdate->Offset = (UINT64)Offset; + LockBoxParameterUpdate->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + LockBoxParameterUpdate->Length = (UINT64)Length; + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunication->Communicate ( + SmmCommunication, + &CommBuffer[0], + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + Status = (EFI_STATUS)LockBoxParameterUpdate->Header.ReturnStatus; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib UpdateLockBox - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + +/** + This function will restore confidential information from lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the restored confidential information + NULL means restored to original address, Length MUST be NULL at same time. + @param Length the length of the restored confidential information + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL. + @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no + LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute. + @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_ACCESS_DENIED not allow to restore to the address + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreLockBox ( + IN GUID *Guid, + IN VOID *Buffer, OPTIONAL + IN OUT UINTN *Length OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)]; + UINTN CommSize; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || + ((Buffer == NULL) && (Length != NULL)) || + ((Buffer != NULL) && (Length == NULL))) { + return EFI_INVALID_PARAMETER; + } + + // + // Get needed resource + // + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&SmmCommunication + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + CommHeader->MessageLength = sizeof(*LockBoxParameterRestore); + + LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + LockBoxParameterRestore->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE; + LockBoxParameterRestore->Header.DataLength = sizeof(*LockBoxParameterRestore); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)-1; + CopyMem (&LockBoxParameterRestore->Guid, Guid, sizeof(*Guid)); + LockBoxParameterRestore->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + if (Length != NULL) { + LockBoxParameterRestore->Length = (EFI_PHYSICAL_ADDRESS)*Length; + } else { + LockBoxParameterRestore->Length = 0; + } + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunication->Communicate ( + SmmCommunication, + &CommBuffer[0], + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + if (Length != NULL) { + *Length = (UINTN)LockBoxParameterRestore->Length; + } + + Status = (EFI_STATUS)LockBoxParameterRestore->Header.ReturnStatus; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreLockBox - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + +/** + This function will restore confidential information from all lockbox which have RestoreInPlace attribute. + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreAllLockBoxInPlace ( + VOID + ) +{ + EFI_STATUS Status; + EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINTN) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)]; + UINTN CommSize; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreAllLockBoxInPlace - Enter\n")); + + // + // Get needed resource + // + Status = gBS->LocateProtocol ( + &gEfiSmmCommunicationProtocolGuid, + NULL, + (VOID **)&SmmCommunication + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + CommHeader->MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace); + + LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + LockBoxParameterRestoreAllInPlace->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE; + LockBoxParameterRestoreAllInPlace->Header.DataLength = sizeof(*LockBoxParameterRestoreAllInPlace); + LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)-1; + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunication->Communicate ( + SmmCommunication, + &CommBuffer[0], + &CommSize + ); + ASSERT_EFI_ERROR (Status); + + Status = (EFI_STATUS)LockBoxParameterRestoreAllInPlace->Header.ReturnStatus; + + DEBUG ((EFI_D_INFO, "SmmLockBoxDxeLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf new file mode 100644 index 0000000000..b9052e7979 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf @@ -0,0 +1,50 @@ +## @file +# Component description file for LockBox library. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions +# of the BSD License which accompanies this distribution. The +# full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmLockBoxDxeLib + FILE_GUID = 4A0054B4-3CA8-4e1b-9339-9B58D5FBB7D2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = LockBoxLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmLockBoxDxeLib.c + SmmLockBoxLibPrivate.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseMemoryLib + DebugLib + +[Guids] + gEfiSmmLockBoxCommunicationGuid ## CONSUMED + +[Protocols] + gEfiSmmCommunicationProtocolGuid ## CONSUMED diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h new file mode 100644 index 0000000000..3dfd03e417 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h @@ -0,0 +1,54 @@ +/** @file + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_LOCK_BOX_LIB_PRIVATE_H_ +#define _SMM_LOCK_BOX_LIB_PRIVATE_H_ + +#include + +#pragma pack(push, 1) + +// +// Below data structure is used for lockbox registration in SMST +// + +#define SMM_LOCK_BOX_SIGNATURE_32 SIGNATURE_64 ('L','O','C','K','B','_','3','2') +#define SMM_LOCK_BOX_SIGNATURE_64 SIGNATURE_64 ('L','O','C','K','B','_','6','4') + +typedef struct { + UINT64 Signature; + EFI_PHYSICAL_ADDRESS LockBoxDataAddress; +} SMM_LOCK_BOX_CONTEXT; + +// +// Below data structure is used for lockbox management +// + +#define SMM_LOCK_BOX_DATA_SIGNATURE SIGNATURE_64 ('L','O','C','K','B','O','X','D') + +typedef struct { + UINT64 Signature; + EFI_GUID Guid; + EFI_PHYSICAL_ADDRESS Buffer; + UINT64 Length; + UINT64 Attributes; + EFI_PHYSICAL_ADDRESS SmramBuffer; + LIST_ENTRY Link; +} SMM_LOCK_BOX_DATA; + +#pragma pack(pop) + +#endif + diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c new file mode 100644 index 0000000000..51e6930a76 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c @@ -0,0 +1,542 @@ +/** @file + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "SmmLockBoxLibPrivate.h" + +/** + We need handle this library carefully. Only one library instance will construct the environment. + Below 2 global variable can only be used in constructor. They should NOT be used in any other library functions. +**/ +SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext; +LIST_ENTRY mLockBoxQueue = INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue); + +/** + This function return SmmLockBox context from SMST. + + @return SmmLockBox context from SMST. +**/ +SMM_LOCK_BOX_CONTEXT * +InternalGetSmmLockBoxContext ( + VOID + ) +{ + UINTN Index; + + // + // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone + // + for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) { + if (CompareGuid (&gSmst->SmmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) { + // + // Found. That means some other library instance is already run. + // No need to install again, just return. + // + return (SMM_LOCK_BOX_CONTEXT *)gSmst->SmmConfigurationTable[Index].VendorTable; + } + } + + // + // Not found. + // + return NULL; +} + +/** + Constructor for SmmLockBox library. + This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A Pointer to the EFI System Table. + + @retval EFI_SUCEESS + @return Others Some error occurs. +**/ +EFI_STATUS +EFIAPI +SmmLockBoxSmmConstructuor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Enter\n")); + + // + // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone + // + SmmLockBoxContext = InternalGetSmmLockBoxContext (); + if (SmmLockBoxContext != NULL) { + // + // Find it. That means some other library instance is already run. + // No need to install again, just return. + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n")); + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n")); + return EFI_SUCCESS; + } + + // + // If no one install this, it means this is first instance. Install it. + // + if (sizeof(UINTN) == sizeof(UINT64)) { + mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_64; + } else { + mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_32; + } + mSmmLockBoxContext.LockBoxDataAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)&mLockBoxQueue; + + Status = gSmst->SmmInstallConfigurationTable ( + gSmst, + &gEfiSmmLockBoxCommunicationGuid, + &mSmmLockBoxContext, + sizeof(mSmmLockBoxContext) + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext)); + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue)); + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n")); + + return Status; +} + +/** + This function return SmmLockBox queue address. + + @return SmmLockBox queue address. +**/ +LIST_ENTRY * +InternalGetLockBoxQueue ( + VOID + ) +{ + SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext; + + SmmLockBoxContext = InternalGetSmmLockBoxContext (); + ASSERT (SmmLockBoxContext != NULL); + if (SmmLockBoxContext == NULL) { + return NULL; + } + return (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress; +} + +/** + This function find LockBox by GUID. + + @param Guid The guid to indentify the LockBox + + @return LockBoxData +**/ +SMM_LOCK_BOX_DATA * +InternalFindLockBoxByGuid ( + IN EFI_GUID *Guid + ) +{ + LIST_ENTRY *Link; + SMM_LOCK_BOX_DATA *LockBox; + LIST_ENTRY *LockBoxQueue; + + LockBoxQueue = InternalGetLockBoxQueue (); + ASSERT (LockBoxQueue != NULL); + + for (Link = LockBoxQueue->ForwardLink; + Link != LockBoxQueue; + Link = Link->ForwardLink) { + LockBox = BASE_CR ( + Link, + SMM_LOCK_BOX_DATA, + Link + ); + if (CompareGuid (&LockBox->Guid, Guid)) { + return LockBox; + } + } + return NULL; +} + +/** + This function will save confidential information to lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the confidential information + @param Length the length of the confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0 + @retval RETURN_ALREADY_STARTED the requested GUID already exist. + @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SaveLockBox ( + IN GUID *Guid, + IN VOID *Buffer, + IN UINTN Length + ) +{ + SMM_LOCK_BOX_DATA *LockBox; + EFI_PHYSICAL_ADDRESS SmramBuffer; + EFI_STATUS Status; + LIST_ENTRY *LockBoxQueue; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + // + // Find LockBox + // + LockBox = InternalFindLockBoxByGuid (Guid); + if (LockBox != NULL) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED)); + return EFI_ALREADY_STARTED; + } + + // + // Allocate SMRAM buffer + // + Status = gSmst->SmmAllocatePages ( + AllocateAnyPages, + EfiRuntimeServicesData, + EFI_SIZE_TO_PAGES (Length), + &SmramBuffer + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES)); + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate LockBox + // + Status = gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + sizeof(*LockBox), + (VOID **)&LockBox + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + gSmst->SmmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length)); + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES)); + return EFI_OUT_OF_RESOURCES; + } + + // + // Save data + // + CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)Buffer, Length); + + // + // Insert LockBox to queue + // + LockBox->Signature = SMM_LOCK_BOX_DATA_SIGNATURE; + CopyMem (&LockBox->Guid, Guid, sizeof(EFI_GUID)); + LockBox->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + LockBox->Length = (UINT64)Length; + LockBox->SmramBuffer = SmramBuffer; + + LockBoxQueue = InternalGetLockBoxQueue (); + ASSERT (LockBoxQueue != NULL); + InsertTailList (LockBoxQueue, &LockBox->Link); + + // + // Done + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + +/** + This function will set lockbox attributes. + + @param Guid the guid to identify the confidential information + @param Attributes the attributes of the lockbox + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER attributes is invalid. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +SetLockBoxAttributes ( + IN GUID *Guid, + IN UINT64 Attributes + ) +{ + SMM_LOCK_BOX_DATA *LockBox; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || + ((Attributes & ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0)) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + // + // Find LockBox + // + LockBox = InternalFindLockBoxByGuid (Guid); + if (LockBox == NULL) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND)); + return EFI_NOT_FOUND; + } + + // + // Update data + // + LockBox->Attributes = Attributes; + + // + // Done + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + +/** + This function will update confidential information to lockbox. + + @param Guid the guid to identify the original confidential information + @param Offset the offset of the original confidential information + @param Buffer the address of the updated confidential information + @param Length the length of the updated confidential information + + @retval RETURN_SUCCESS the information is saved successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information. + @retval RETURN_ACCESS_DENIED it is too late to invoke this interface + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +UpdateLockBox ( + IN GUID *Guid, + IN UINTN Offset, + IN VOID *Buffer, + IN UINTN Length + ) +{ + SMM_LOCK_BOX_DATA *LockBox; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + // + // Find LockBox + // + LockBox = InternalFindLockBoxByGuid (Guid); + if (LockBox == NULL) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND)); + return EFI_NOT_FOUND; + } + + // + // Update data + // + if (LockBox->Length < Offset + Length) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL)); + return EFI_BUFFER_TOO_SMALL; + } + CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length); + + // + // Done + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + +/** + This function will restore confidential information from lockbox. + + @param Guid the guid to identify the confidential information + @param Buffer the address of the restored confidential information + NULL means restored to original address, Length MUST be NULL at same time. + @param Length the length of the restored confidential information + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL. + @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no + LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute. + @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information. + @retval RETURN_NOT_FOUND the requested GUID not found. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_ACCESS_DENIED not allow to restore to the address + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreLockBox ( + IN GUID *Guid, + IN VOID *Buffer, OPTIONAL + IN OUT UINTN *Length OPTIONAL + ) +{ + SMM_LOCK_BOX_DATA *LockBox; + VOID *RestoreBuffer; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n")); + + // + // Restore this, Buffer and Length MUST be both NULL or both non-NULL + // + if ((Guid == NULL) || + ((Buffer == NULL) && (Length != NULL)) || + ((Buffer != NULL) && (Length == NULL))) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + // + // Find LockBox + // + LockBox = InternalFindLockBoxByGuid (Guid); + if (LockBox == NULL) { + // + // Not found + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND)); + return EFI_NOT_FOUND; + } + + // + // Set RestoreBuffer + // + if (Buffer != NULL) { + // + // restore to new buffer + // + RestoreBuffer = Buffer; + } else { + // + // restore to original buffer + // + if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) { + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED)); + return EFI_WRITE_PROTECTED; + } + RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer; + } + + // + // Set RestoreLength + // + if (Length != NULL) { + if (*Length < (UINTN)LockBox->Length) { + // + // Input buffer is too small to hold all data. + // + *Length = (UINTN)LockBox->Length; + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL)); + return EFI_BUFFER_TOO_SMALL; + } + *Length = (UINTN)LockBox->Length; + } + + // + // Restore data + // + CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length); + + // + // Done + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + +/** + This function will restore confidential information from all lockbox which have RestoreInPlace attribute. + + @retval RETURN_SUCCESS the information is restored successfully. + @retval RETURN_NOT_STARTED it is too early to invoke this interface + @retval RETURN_UNSUPPORTED the service is not supported by implementaion. +**/ +RETURN_STATUS +EFIAPI +RestoreAllLockBoxInPlace ( + VOID + ) +{ + SMM_LOCK_BOX_DATA *LockBox; + LIST_ENTRY *Link; + LIST_ENTRY *LockBoxQueue; + + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n")); + + LockBoxQueue = InternalGetLockBoxQueue (); + ASSERT (LockBoxQueue != NULL); + + // + // Restore all, Buffer and Length MUST be NULL + // + for (Link = LockBoxQueue->ForwardLink; + Link != LockBoxQueue; + Link = Link->ForwardLink) { + LockBox = BASE_CR ( + Link, + SMM_LOCK_BOX_DATA, + Link + ); + if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) { + // + // Restore data + // + CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length); + } + } + // + // Done + // + DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS)); + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf new file mode 100644 index 0000000000..49d0952822 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf @@ -0,0 +1,46 @@ +## @file +# Component description file for LockBox library. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions +# of the BSD License which accompanies this distribution. The +# full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmLockBoxSmmLib + FILE_GUID = E04894D6-290D-4171-A362-0ACFD939F3C8 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = LockBoxLib|DXE_SMM_DRIVER + CONSTRUCTOR = SmmLockBoxSmmConstructuor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmLockBoxSmmLib.c + SmmLockBoxLibPrivate.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + SmmServicesTableLib + BaseLib + DebugLib + +[Guids] + gEfiSmmLockBoxCommunicationGuid ## COMSUMED diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 0a9cdcd9b4..0ebf033f30 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -185,6 +185,9 @@ ## Include/Guid/RecoveryDevice.h gRecoveryOnDataCdGuid = { 0x5CAC0099, 0x0DC9, 0x48E5, { 0x80, 0x68, 0xBB, 0x95, 0xF5, 0x40, 0x0A, 0x9F }} + ## Include/Guid/SmmLockBox.h + gEfiSmmLockBoxCommunicationGuid = { 0x2a3cfebd, 0x27e8, 0x4d0a, { 0x8b, 0x79, 0xd6, 0x88, 0xc2, 0xa3, 0xe1, 0xc0 }} + [Ppis] ## Include/Ppi/AtaController.h gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }} @@ -255,6 +258,10 @@ ## This protocol allows the error level mask for DEBUG() macros to be adjusted for DXE Phase modules # Include/Guid/DebugMask.h gEfiDebugMaskProtocolGuid = { 0x4c8a2451, 0xc207, 0x405b, {0x96, 0x94, 0x99, 0xea, 0x13, 0x25, 0x13, 0x41} } + + ## Include/Protocol/LockBox.h + gEfiLockBoxProtocolGuid = { 0xbd445d79, 0xb7ad, 0x4f04, { 0x9a, 0xd8, 0x29, 0xbd, 0x20, 0x40, 0xeb, 0x3c }} + [PcdsFeatureFlag] ## Indicate whether platform can support update capsule across a system reset gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE|BOOLEAN|0x0001001d diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 171a8d0323..af66ca1387 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -107,12 +107,14 @@ [LibraryClasses.common.DXE_DRIVER] HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf [LibraryClasses.common.DXE_RUNTIME_DRIVER] HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf [LibraryClasses.common.SMM_CORE] MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf @@ -123,11 +125,13 @@ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf [LibraryClasses.common.UEFI_DRIVER] HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf [LibraryClasses.common.UEFI_APPLICATION] HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf @@ -232,6 +236,8 @@ MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf + MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf MdeModulePkg/Universal/CapsulePei/CapsulePei.inf MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf @@ -309,6 +315,7 @@ MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf + MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf diff --git a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c new file mode 100644 index 0000000000..1f9c3b4836 --- /dev/null +++ b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c @@ -0,0 +1,373 @@ +/** @file + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BOOLEAN mLocked = FALSE; + +EFI_SMRAM_DESCRIPTOR *mSmramRanges; +UINTN mSmramRangeCount; + +/** + This function check if the address is in SMRAM. + + @param Buffer the buffer address to be checked. + @param Length the buffer length to be checked. + + @retval TRUE this address is in SMRAM. + @retval FALSE this address is NOT in SMRAM. +**/ +BOOLEAN +IsAddressInSmram ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length + ) +{ + UINTN Index; + + for (Index = 0; Index < mSmramRangeCount; Index ++) { + if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) || + ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) { + return TRUE; + } + } + + return FALSE; +} + +/** + Dispatch function for SMM lock box save. + + @param LockBoxParameterSave parameter of lock box save +**/ +VOID +SmmLockBoxSave ( + IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave + ) +{ + EFI_STATUS Status; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + // + // Save data + // + Status = SaveLockBox ( + &LockBoxParameterSave->Guid, + (VOID *)(UINTN)LockBoxParameterSave->Buffer, + (UINTN)LockBoxParameterSave->Length + ); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box set attributes. + + @param LockBoxParameterSetAttributes parameter of lock box set attributes +**/ +VOID +SmmLockBoxSetAttributes ( + IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes + ) +{ + EFI_STATUS Status; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + // + // Update data + // + Status = SetLockBoxAttributes ( + &LockBoxParameterSetAttributes->Guid, + LockBoxParameterSetAttributes->Attributes + ); + LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box update. + + @param LockBoxParameterUpdate parameter of lock box update +**/ +VOID +SmmLockBoxUpdate ( + IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate + ) +{ + EFI_STATUS Status; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + // + // Update data + // + Status = UpdateLockBox ( + &LockBoxParameterUpdate->Guid, + (UINTN)LockBoxParameterUpdate->Offset, + (VOID *)(UINTN)LockBoxParameterUpdate->Buffer, + (UINTN)LockBoxParameterUpdate->Length + ); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box restore. + + @param LockBoxParameterRestore parameter of lock box restore +**/ +VOID +SmmLockBoxRestore ( + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore + ) +{ + EFI_STATUS Status; + + // + // Sanity check + // + if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n")); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + // + // Restore data + // + Status = RestoreLockBox ( + &LockBoxParameterRestore->Guid, + (VOID *)(UINTN)LockBoxParameterRestore->Buffer, + (UINTN *)&LockBoxParameterRestore->Length + ); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box restore all in place. + + @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place +**/ +VOID +SmmLockBoxRestoreAllInPlace ( + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace + ) +{ + EFI_STATUS Status; + + Status = RestoreAllLockBoxInPlace (); + LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for a Software SMI handler. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the + handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS Command is handled successfully. + +**/ +EFI_STATUS +EFIAPI +SmmLockBoxHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader; + + DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n")); + + LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer); + + LockBoxParameterHeader->ReturnStatus = (UINT64)-1; + + DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader)); + + DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command)); + + switch (LockBoxParameterHeader->Command) { + case EFI_SMM_LOCK_BOX_COMMAND_SAVE: + SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader); + break; + case EFI_SMM_LOCK_BOX_COMMAND_UPDATE: + SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader); + break; + case EFI_SMM_LOCK_BOX_COMMAND_RESTORE: + SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader); + break; + case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES: + SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader); + break; + case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE: + SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader); + break; + default: + break; + } + + LockBoxParameterHeader->Command = (UINT32)-1; + + DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n")); + + return EFI_SUCCESS; +} + +/** + Smm Ready To Lock event notification handler. + + It sets a flag indicating that SMRAM has been locked. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification handler runs successfully. + **/ +EFI_STATUS +EFIAPI +SmmReadyToLockEventNotify ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + mLocked = TRUE; + return EFI_SUCCESS; +} + +/** + Entry Point for LockBox SMM driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A Pointer to the EFI System Table. + + @retval EFI_SUCEESS + @return Others Some error occurs. +**/ +EFI_STATUS +EFIAPI +SmmLockBoxEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE DispatchHandle; + VOID *Registration; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + UINTN Size; + + // + // Get SMRAM information + // + Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess); + ASSERT_EFI_ERROR (Status); + + Size = 0; + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + Status = gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, + Size, + (VOID **)&mSmramRanges + ); + ASSERT_EFI_ERROR (Status); + + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges); + ASSERT_EFI_ERROR (Status); + + mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + // + // Register LockBox communication handler + // + Status = gSmst->SmiHandlerRegister ( + SmmLockBoxHandler, + &gEfiSmmLockBoxCommunicationGuid, + &DispatchHandle + ); + ASSERT_EFI_ERROR (Status); + + // + // Register SMM Ready To Lock Protocol notification + // + Status = gSmst->SmmRegisterProtocolNotify ( + &gEfiSmmReadyToLockProtocolGuid, + SmmReadyToLockEventNotify, + &Registration + ); + ASSERT_EFI_ERROR (Status); + + // + // Install NULL to DXE data base as notify + // + ImageHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiLockBoxProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf new file mode 100644 index 0000000000..94ec412221 --- /dev/null +++ b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf @@ -0,0 +1,59 @@ +## @file +# Component description file for LockBox SMM driver. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions +# of the BSD License which accompanies this distribution. The +# full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmLockBox + FILE_GUID = 33FB3535-F15E-4c17-B303-5EB94595ECB6 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = SmmLockBoxEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmLockBox.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + SmmServicesTableLib + BaseLib + BaseMemoryLib + DebugLib + LockBoxLib + +[Guids] + gEfiSmmLockBoxCommunicationGuid ## PRODUCED + +[Protocols] + gEfiSmmReadyToLockProtocolGuid ## CONSUMED + gEfiSmmAccess2ProtocolGuid ## CONSUMED + gEfiLockBoxProtocolGuid ## PRODUCED + +[Depex] + gEfiSmmSwDispatch2ProtocolGuid + -- 2.39.2