* [PATCH v1 0/2] Support MM based variable services in PEI for ARM @ 2023-06-08 20:44 Kun Qin 2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin 2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin 0 siblings, 2 replies; 8+ messages in thread From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw) To: devel Cc: Hao A Wu, Liming Gao, Jian J Wang, Leif Lindholm, Ard Biesheuvel, Sami Mujawar REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 As of today, there has been a void in the variable service in PEI phase on ARM systems that support PEI phase and standalone MM hosted variable service. This change adds the support through: 1. Add MM communication services in PEI phase for ARM platforms. This module is based on SMC calls to standalone MM environments, similar to "ArmPkg/Drivers/MmCommunicationDxe". 2. A service module that installs `gEfiPeiReadOnlyVariable2PpiGuid` based on step 1. Note that this driver will not have special dependency on ARM specific code, thus will be ideally added to MdeModulePkg. Patch v1 branch: https://github.com/kuqin12/edk2/tree/arm_var_pei_v1 Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Leif Lindholm <quic_llindhol@quicinc.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Sami Mujawar <sami.mujawar@arm.com> Kun Qin (2): ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI MdeModulePkg: Variable: Introduce MM based variable read service in PEI ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c | 178 +++++++++ MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c | 381 ++++++++++++++++++++ ArmPkg/ArmPkg.dsc | 2 + ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h | 76 ++++ ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf | 41 +++ MdeModulePkg/MdeModulePkg.dsc | 1 + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h | 134 +++++++ MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf | 43 +++ 8 files changed, 856 insertions(+) create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf -- 2.40.1.windows.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI 2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin @ 2023-06-08 20:44 ` Kun Qin 2023-06-22 19:17 ` Sami Mujawar 2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin 1 sibling, 1 reply; 8+ messages in thread From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw) To: devel Cc: Leif Lindholm, Ard Biesheuvel, Sami Mujawar, Ronny Hansen, Shriram Masanamuthu Chinnathurai, Preshit Harlikar From: Kun Qin <kuqin@microsoft.com> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 This change introduced the MM communicate support in PEI phase for ARM based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is used as communicate buffer and SMC will be invoked to communicate to TrustZone when MMI is requested. Cc: Leif Lindholm <quic_llindhol@quicinc.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Sami Mujawar <sami.mujawar@arm.com> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com> Co-authored-by: Shriram Masanamuthu Chinnathurai <shriramma@microsoft.com> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com> Signed-off-by: Kun Qin <kuqin@microsoft.com> --- ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c | 178 ++++++++++++++++++++ ArmPkg/ArmPkg.dsc | 2 + ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h | 76 +++++++++ ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf | 41 +++++ 4 files changed, 297 insertions(+) diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c new file mode 100644 index 000000000000..0f1f763a347d --- /dev/null +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c @@ -0,0 +1,178 @@ +/** @file -- MmCommunicationPei.c + Provides an interface to send MM request in PEI + + Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR> + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "MmCommunicationPei.h" + +// +// Module globals +// +EFI_PEI_MM_COMMUNICATION_PPI mPeiMmCommunication = { + MmCommunicationPeim +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiMmCommunicationPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMmCommunicationPpiGuid, + &mPeiMmCommunication +}; + +/** + Entry point of PEI MM Communication driver + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() +**/ +EFI_STATUS +EFIAPI +MmCommunicationPeiInitialize ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + return PeiServicesInstallPpi (&mPeiMmCommunicationPpi); +} + +/** + MmCommunicationPeim + Communicates with a registered handler. + This function provides a service to send and receive messages from a registered UEFI service during PEI. + + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. + @param[in, out] CommBuffer Pointer to the data buffer + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the + size of data being returned. Zero if the handler does not + wish to reply with any data. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. + If this error is returned, the MessageLength field + in the CommBuffer header or the integer pointed by + CommSize, are updated to reflect the maximum payload + size the implementation can accommodate. + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, + if not omitted, are in address range that cannot be + accessed by the MM environment. +**/ +EFI_STATUS +EFIAPI +MmCommunicationPeim ( + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize + ) +{ + EFI_MM_COMMUNICATE_HEADER *CommunicateHeader; + ARM_SMC_ARGS CommunicateSmcArgs; + EFI_STATUS Status; + UINTN BufferSize; + + Status = EFI_ACCESS_DENIED; + BufferSize = 0; + + ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS)); + + // Check that our static buffer is looking good. + // We are using PcdMmBufferBase to transfer variable data. + // We are not using the full size of the buffer since there is a cost + // of copying data between Normal and Secure World. + ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0); + + // + // Check parameters + // + if (CommBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // If the length of the CommBuffer is 0 then return the expected length. + // This case can be used by the consumer of this driver to find out the + // max size that can be used for allocating CommBuffer. + if ((CommSize != NULL) && \ + ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize)))) + { + *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize); + return EFI_BAD_BUFFER_SIZE; + } + + CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase)); + + CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize); + + // CommBuffer is a mandatory parameter. Hence, Rely on + // MessageLength + Header to ascertain the + // total size of the communication payload rather than + // rely on optional CommSize parameter + BufferSize = CommunicateHeader->MessageLength + + sizeof (CommunicateHeader->HeaderGuid) + + sizeof (CommunicateHeader->MessageLength); + + // + // If CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER); + // + if ((CommSize != NULL) && (*CommSize != BufferSize)) { + return EFI_INVALID_PARAMETER; + } + + // SMC Function ID + CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64; + + // Cookie + CommunicateSmcArgs.Arg1 = 0; + + // comm_buffer_address (64-bit physical address) + CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader; + + // comm_size_address (not used, indicated by setting to zero) + CommunicateSmcArgs.Arg3 = 0; + + // Call the Standalone MM environment. + ArmCallSmc (&CommunicateSmcArgs); + + switch (CommunicateSmcArgs.Arg0) { + case ARM_SMC_MM_RET_SUCCESS: + // On successful return, the size of data being returned is inferred from + // MessageLength + Header. + BufferSize = CommunicateHeader->MessageLength + + sizeof (CommunicateHeader->HeaderGuid) + + sizeof (CommunicateHeader->MessageLength); + CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize); + if (CommSize != NULL) { + *CommSize = BufferSize; + } + + Status = EFI_SUCCESS; + break; + + case ARM_SMC_MM_RET_INVALID_PARAMS: + Status = EFI_INVALID_PARAMETER; + break; + + case ARM_SMC_MM_RET_DENIED: + Status = EFI_ACCESS_DENIED; + break; + + case ARM_SMC_MM_RET_NO_MEMORY: + // Unexpected error since the CommSize was checked for zero length + // prior to issuing the SMC + Status = EFI_OUT_OF_RESOURCES; + ASSERT (0); + break; + + default: + Status = EFI_ACCESS_DENIED; + ASSERT (0); + } + + return Status; +} diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 6b938ce8b671..4939b3d59b7f 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -162,6 +162,8 @@ [Components.common] ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf + ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf + [Components.AARCH64] ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h new file mode 100644 index 000000000000..a99baa2496a9 --- /dev/null +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h @@ -0,0 +1,76 @@ +/** @file -- MmCommunicationPei.h + Provides an interface to send MM request in PEI + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef MM_COMMUNICATION_PEI_H_ +#define MM_COMMUNICATION_PEI_H_ + +#include <PiPei.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/ArmSmcLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/PeimEntryPoint.h> +#include <Library/PeiServicesLib.h> +#include <Library/HobLib.h> + +#include <Protocol/MmCommunication.h> + +#include <IndustryStandard/ArmStdSmc.h> + +#include <Ppi/MmCommunication.h> + +/** + Entry point of PEI MM Communication driver + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() +**/ +EFI_STATUS +EFIAPI +MmCommunicationPeiInitialize ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + MmCommunicationPeim + Communicates with a registered handler. + This function provides a service to send and receive messages from a registered UEFI service during PEI. + + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. + @param[in, out] CommBuffer Pointer to the data buffer + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the + size of data being returned. Zero if the handler does not + wish to reply with any data. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. + If this error is returned, the MessageLength field + in the CommBuffer header or the integer pointed by + CommSize, are updated to reflect the maximum payload + size the implementation can accommodate. + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, + if not omitted, are in address range that cannot be + accessed by the MM environment. +**/ +EFI_STATUS +EFIAPI +MmCommunicationPeim ( + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize + ); + +#endif /* MM_COMMUNICATION_PEI_H_ */ diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf new file mode 100644 index 000000000000..f4e359dafd75 --- /dev/null +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf @@ -0,0 +1,41 @@ +## @file -- MmCommunicationPei.inf +# PEI MM Communicate driver +# +# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR> +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MmCommunicationPei + FILE_GUID = 58FFB346-1B75-42C7-AD69-37C652423C1A + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = MmCommunicationPeiInitialize + +[Sources] + MmCommunicationPei.c + MmCommunicationPei.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + DebugLib + ArmSmcLib + PeimEntryPoint + PeiServicesLib + HobLib + +[Pcd] + gArmTokenSpaceGuid.PcdMmBufferBase + gArmTokenSpaceGuid.PcdMmBufferSize + +[Ppis] + gEfiPeiMmCommunicationPpiGuid ## PRODUCES + +[Depex] + TRUE -- 2.40.1.windows.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI 2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin @ 2023-06-22 19:17 ` Sami Mujawar 2023-06-26 20:07 ` Kun Qin 0 siblings, 1 reply; 8+ messages in thread From: Sami Mujawar @ 2023-06-22 19:17 UTC (permalink / raw) To: Kun Qin, devel Cc: Leif Lindholm, Ard Biesheuvel, Ronny Hansen, Shriram Masanamuthu Chinnathurai, Preshit Harlikar, nd@arm.com [-- Attachment #1: Type: text/plain, Size: 14979 bytes --] Hi Kun, Thank you for this patch. Please find my response inline marked [SAMI]. Regards, Sami Mujawar On 08/06/2023 09:44 pm, Kun Qin wrote: > From: Kun Qin<kuqin@microsoft.com> > > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4464 > > This change introduced the MM communicate support in PEI phase for ARM > based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is > used as communicate buffer and SMC will be invoked to communicate to > TrustZone when MMI is requested. > > Cc: Leif Lindholm<quic_llindhol@quicinc.com> > Cc: Ard Biesheuvel<ardb+tianocore@kernel.org> > Cc: Sami Mujawar<sami.mujawar@arm.com> > > Co-authored-by: Ronny Hansen<hansen.ronny@microsoft.com> > Co-authored-by: Shriram Masanamuthu Chinnathurai<shriramma@microsoft.com> > Co-authored-by: Preshit Harlikar<pharlikar@microsoft.com> > Signed-off-by: Kun Qin<kuqin@microsoft.com> > --- > ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c | 178 ++++++++++++++++++++ > ArmPkg/ArmPkg.dsc | 2 + > ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h | 76 +++++++++ > ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf | 41 +++++ > 4 files changed, 297 insertions(+) > > diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c > new file mode 100644 > index 000000000000..0f1f763a347d > --- /dev/null > +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c > @@ -0,0 +1,178 @@ > +/** @file -- MmCommunicationPei.c > > + Provides an interface to send MM request in PEI > > + > > + Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR> > > + Copyright (c) Microsoft Corporation. > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "MmCommunicationPei.h" > > + > > +// > > +// Module globals > > +// > > +EFI_PEI_MM_COMMUNICATION_PPI mPeiMmCommunication = { > > + MmCommunicationPeim > > +}; > > + > > +EFI_PEI_PPI_DESCRIPTOR mPeiMmCommunicationPpi = { > > + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > > + &gEfiPeiMmCommunicationPpiGuid, > > + &mPeiMmCommunication > > +}; > > + > > +/** > > + Entry point of PEI MM Communication driver > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). > > + @param PeiServices General purpose services available to every PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > +**/ > > +EFI_STATUS > > +EFIAPI > > +MmCommunicationPeiInitialize ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ) > > +{ > > + return PeiServicesInstallPpi (&mPeiMmCommunicationPpi); > > +} > > + > > +/** > > + MmCommunicationPeim > > + Communicates with a registered handler. > > + This function provides a service to send and receive messages from a registered UEFI service during PEI. > > + > > + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. > > + @param[in, out] CommBuffer Pointer to the data buffer > > + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the > > + size of data being returned. Zero if the handler does not > > + wish to reply with any data. > > + > > + @retval EFI_SUCCESS The message was successfully posted. > > + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match > > + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). > > + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. > > + If this error is returned, the MessageLength field > > + in the CommBuffer header or the integer pointed by > > + CommSize, are updated to reflect the maximum payload > > + size the implementation can accommodate. > > + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, > > + if not omitted, are in address range that cannot be > > + accessed by the MM environment. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +MmCommunicationPeim ( > > + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, > > + IN OUT VOID *CommBuffer, > > + IN OUT UINTN *CommSize > > + ) > > +{ > > + EFI_MM_COMMUNICATE_HEADER *CommunicateHeader; > > + ARM_SMC_ARGS CommunicateSmcArgs; > > + EFI_STATUS Status; > > + UINTN BufferSize; > > + > > + Status = EFI_ACCESS_DENIED; > > + BufferSize = 0; [SAMI] Minor optimisation: The above initialisations are probably not required. > > + > > + ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS)); > > + > > + // Check that our static buffer is looking good. > > + // We are using PcdMmBufferBase to transfer variable data. > > + // We are not using the full size of the buffer since there is a cost > > + // of copying data between Normal and Secure World. > > + ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0); > > + > > + // > > + // Check parameters > > + // > > + if (CommBuffer == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } [SAMI] Should there be a check for CommSize as well? Otherwise the code will crash a few lines below when doing CopyMem(). > + > > + // If the length of the CommBuffer is 0 then return the expected length. > > + // This case can be used by the consumer of this driver to find out the > > + // max size that can be used for allocating CommBuffer. > > + if ((CommSize != NULL) && \ > > + ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize)))) > > + { > > + *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase)); > > + > > + CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize); [SAMI] If CommSize is NULL, the above the above line will result in a crash, right? > > + > > + // CommBuffer is a mandatory parameter. Hence, Rely on > > + // MessageLength + Header to ascertain the > > + // total size of the communication payload rather than > > + // rely on optional CommSize parameter > > + BufferSize = CommunicateHeader->MessageLength + > > + sizeof (CommunicateHeader->HeaderGuid) + > > + sizeof (CommunicateHeader->MessageLength); > > + > > + // > > + // If CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER); > > + // > > + if ((CommSize != NULL) && (*CommSize != BufferSize)) { > > + return EFI_INVALID_PARAMETER; > > + } [SAMI] It may be better to do this check earlier in the code by casting CommBuffer to EFI_MM_COMMUNICATE_HEADER * and calculating the BufferSize. That way the CopyMem() above can be avoided if the above test fails. > > + > > + // SMC Function ID > > + CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64; > > + > > + // Cookie > > + CommunicateSmcArgs.Arg1 = 0; > > + > > + // comm_buffer_address (64-bit physical address) > > + CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader; > > + > > + // comm_size_address (not used, indicated by setting to zero) > > + CommunicateSmcArgs.Arg3 = 0; > > + > > + // Call the Standalone MM environment. > > + ArmCallSmc (&CommunicateSmcArgs); > > + > > + switch (CommunicateSmcArgs.Arg0) { > > + case ARM_SMC_MM_RET_SUCCESS: > > + // On successful return, the size of data being returned is inferred from > > + // MessageLength + Header. > > + BufferSize = CommunicateHeader->MessageLength + > > + sizeof (CommunicateHeader->HeaderGuid) + > > + sizeof (CommunicateHeader->MessageLength); > > + CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize); [SAMI] Can there be a case where the returned MessageLength results in the CommBuffer size being smaller, i.e. BufferSize returned > *CommSize ? I expect ARM_SMC_MM_RET_NO_MEMORY to have been returned in the first place, but it may be worth adding a check to avoid potential issues. What do you think? > > + if (CommSize != NULL) { > > + *CommSize = BufferSize; > > + } > > + > > + Status = EFI_SUCCESS; > > + break; > > + > > + case ARM_SMC_MM_RET_INVALID_PARAMS: > > + Status = EFI_INVALID_PARAMETER; > > + break; > > + > > + case ARM_SMC_MM_RET_DENIED: > > + Status = EFI_ACCESS_DENIED; > > + break; > > + > > + case ARM_SMC_MM_RET_NO_MEMORY: > > + // Unexpected error since the CommSize was checked for zero length > > + // prior to issuing the SMC > > + Status = EFI_OUT_OF_RESOURCES; > > + ASSERT (0); > > + break; > > + > > + default: > > + Status = EFI_ACCESS_DENIED; > > + ASSERT (0); > > + } > > + > > + return Status; > > +} > > diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc > index 6b938ce8b671..4939b3d59b7f 100644 > --- a/ArmPkg/ArmPkg.dsc > +++ b/ArmPkg/ArmPkg.dsc > @@ -162,6 +162,8 @@ [Components.common] > ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf > > ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf > > > > + ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf > > + > > [Components.AARCH64] > > ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf > > ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf > > diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h > new file mode 100644 > index 000000000000..a99baa2496a9 > --- /dev/null > +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h > @@ -0,0 +1,76 @@ > +/** @file -- MmCommunicationPei.h > > + Provides an interface to send MM request in PEI > > + > > + Copyright (c) Microsoft Corporation. > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef MM_COMMUNICATION_PEI_H_ > > +#define MM_COMMUNICATION_PEI_H_ > > + > > +#include <PiPei.h> > > + > > +#include <Library/BaseLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/ArmSmcLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/PeimEntryPoint.h> > > +#include <Library/PeiServicesLib.h> > > +#include <Library/HobLib.h> > > + > > +#include <Protocol/MmCommunication.h> > > + > > +#include <IndustryStandard/ArmStdSmc.h> > > + > > +#include <Ppi/MmCommunication.h> > > + > > +/** > > + Entry point of PEI MM Communication driver > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). > > + @param PeiServices General purpose services available to every PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > +**/ > > +EFI_STATUS > > +EFIAPI > > +MmCommunicationPeiInitialize ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ); > > + > > +/** > > + MmCommunicationPeim > > + Communicates with a registered handler. > > + This function provides a service to send and receive messages from a registered UEFI service during PEI. > > + > > + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. > > + @param[in, out] CommBuffer Pointer to the data buffer > > + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the > > + size of data being returned. Zero if the handler does not > > + wish to reply with any data. > > + > > + @retval EFI_SUCCESS The message was successfully posted. > > + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match > > + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). > > + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. > > + If this error is returned, the MessageLength field > > + in the CommBuffer header or the integer pointed by > > + CommSize, are updated to reflect the maximum payload > > + size the implementation can accommodate. > > + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, > > + if not omitted, are in address range that cannot be > > + accessed by the MM environment. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +MmCommunicationPeim ( > > + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, > > + IN OUT VOID *CommBuffer, > > + IN OUT UINTN *CommSize > > + ); > > + > > +#endif /* MM_COMMUNICATION_PEI_H_ */ > > diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf > new file mode 100644 > index 000000000000..f4e359dafd75 > --- /dev/null > +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf > @@ -0,0 +1,41 @@ > +## @file -- MmCommunicationPei.inf > > +# PEI MM Communicate driver > > +# > > +# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR> > > +# Copyright (c) Microsoft Corporation. > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 [SAMI] The version should be |0x0001001B. See https://github.com/tianocore-docs/edk2-InfSpecification/blob/master/3_edk_ii_inf_file_format/34_%5Bdefines%5D_section.md | > > + BASE_NAME = MmCommunicationPei > > + FILE_GUID = 58FFB346-1B75-42C7-AD69-37C652423C1A > > + MODULE_TYPE = PEIM > > + VERSION_STRING = 1.0 > > + ENTRY_POINT = MmCommunicationPeiInitialize > > + > > +[Sources] > > + MmCommunicationPei.c > > + MmCommunicationPei.h > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + ArmPkg/ArmPkg.dec > > + > > +[LibraryClasses] > > + DebugLib > > + ArmSmcLib > > + PeimEntryPoint > > + PeiServicesLib > > + HobLib > > + > > +[Pcd] > > + gArmTokenSpaceGuid.PcdMmBufferBase > > + gArmTokenSpaceGuid.PcdMmBufferSize > > + > > +[Ppis] > > + gEfiPeiMmCommunicationPpiGuid ## PRODUCES > > + > > +[Depex] > > + TRUE > [-- Attachment #2: Type: text/html, Size: 16433 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI 2023-06-22 19:17 ` Sami Mujawar @ 2023-06-26 20:07 ` Kun Qin 0 siblings, 0 replies; 8+ messages in thread From: Kun Qin @ 2023-06-26 20:07 UTC (permalink / raw) To: Sami Mujawar, devel Cc: Leif Lindholm, Ard Biesheuvel, Ronny Hansen, Shriram Masanamuthu Chinnathurai, Preshit Harlikar, nd@arm.com [-- Attachment #1: Type: text/plain, Size: 15910 bytes --] Hi Sami, Thank you for your feedback. I have update the code as you suggested. Could you please re-review when you have a chance? https://edk2.groups.io/g/devel/message/106372 Thanks, Kun On 6/22/2023 12:17 PM, Sami Mujawar wrote: > > Hi Kun, > > Thank you for this patch. > > Please find my response inline marked [SAMI]. > > Regards, > > Sami Mujawar > > On 08/06/2023 09:44 pm, Kun Qin wrote: >> From: Kun Qin<kuqin@microsoft.com> >> >> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4464 >> >> This change introduced the MM communicate support in PEI phase for ARM >> based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is >> used as communicate buffer and SMC will be invoked to communicate to >> TrustZone when MMI is requested. >> >> Cc: Leif Lindholm<quic_llindhol@quicinc.com> >> Cc: Ard Biesheuvel<ardb+tianocore@kernel.org> >> Cc: Sami Mujawar<sami.mujawar@arm.com> >> >> Co-authored-by: Ronny Hansen<hansen.ronny@microsoft.com> >> Co-authored-by: Shriram Masanamuthu Chinnathurai<shriramma@microsoft.com> >> Co-authored-by: Preshit Harlikar<pharlikar@microsoft.com> >> Signed-off-by: Kun Qin<kuqin@microsoft.com> >> --- >> ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c | 178 ++++++++++++++++++++ >> ArmPkg/ArmPkg.dsc | 2 + >> ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h | 76 +++++++++ >> ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf | 41 +++++ >> 4 files changed, 297 insertions(+) >> >> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c >> new file mode 100644 >> index 000000000000..0f1f763a347d >> --- /dev/null >> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c >> @@ -0,0 +1,178 @@ >> +/** @file -- MmCommunicationPei.c >> >> + Provides an interface to send MM request in PEI >> >> + >> >> + Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR> >> >> + Copyright (c) Microsoft Corporation. >> >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +**/ >> >> + >> >> +#include "MmCommunicationPei.h" >> >> + >> >> +// >> >> +// Module globals >> >> +// >> >> +EFI_PEI_MM_COMMUNICATION_PPI mPeiMmCommunication = { >> >> + MmCommunicationPeim >> >> +}; >> >> + >> >> +EFI_PEI_PPI_DESCRIPTOR mPeiMmCommunicationPpi = { >> >> + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), >> >> + &gEfiPeiMmCommunicationPpiGuid, >> >> + &mPeiMmCommunication >> >> +}; >> >> + >> >> +/** >> >> + Entry point of PEI MM Communication driver >> >> + >> >> + @param FileHandle Handle of the file being invoked. >> >> + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). >> >> + @param PeiServices General purpose services available to every PEIM. >> >> + >> >> + @retval EFI_SUCCESS If the interface could be successfully installed >> >> + @retval Others Returned from PeiServicesInstallPpi() >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +MmCommunicationPeiInitialize ( >> >> + IN EFI_PEI_FILE_HANDLE FileHandle, >> >> + IN CONST EFI_PEI_SERVICES **PeiServices >> >> + ) >> >> +{ >> >> + return PeiServicesInstallPpi (&mPeiMmCommunicationPpi); >> >> +} >> >> + >> >> +/** >> >> + MmCommunicationPeim >> >> + Communicates with a registered handler. >> >> + This function provides a service to send and receive messages from a registered UEFI service during PEI. >> >> + >> >> + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. >> >> + @param[in, out] CommBuffer Pointer to the data buffer >> >> + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the >> >> + size of data being returned. Zero if the handler does not >> >> + wish to reply with any data. >> >> + >> >> + @retval EFI_SUCCESS The message was successfully posted. >> >> + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match >> >> + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). >> >> + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. >> >> + If this error is returned, the MessageLength field >> >> + in the CommBuffer header or the integer pointed by >> >> + CommSize, are updated to reflect the maximum payload >> >> + size the implementation can accommodate. >> >> + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, >> >> + if not omitted, are in address range that cannot be >> >> + accessed by the MM environment. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +MmCommunicationPeim ( >> >> + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, >> >> + IN OUT VOID *CommBuffer, >> >> + IN OUT UINTN *CommSize >> >> + ) >> >> +{ >> >> + EFI_MM_COMMUNICATE_HEADER *CommunicateHeader; >> >> + ARM_SMC_ARGS CommunicateSmcArgs; >> >> + EFI_STATUS Status; >> >> + UINTN BufferSize; >> >> + >> >> + Status = EFI_ACCESS_DENIED; >> >> + BufferSize = 0; > [SAMI] Minor optimisation: The above initialisations are probably not > required. >> + >> >> + ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS)); >> >> + >> >> + // Check that our static buffer is looking good. >> >> + // We are using PcdMmBufferBase to transfer variable data. >> >> + // We are not using the full size of the buffer since there is a cost >> >> + // of copying data between Normal and Secure World. >> >> + ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0); >> >> + >> >> + // >> >> + // Check parameters >> >> + // >> >> + if (CommBuffer == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } > [SAMI] Should there be a check for CommSize as well? Otherwise the > code will crash a few lines below when doing CopyMem(). >> + >> >> + // If the length of the CommBuffer is 0 then return the expected length. >> >> + // This case can be used by the consumer of this driver to find out the >> >> + // max size that can be used for allocating CommBuffer. >> >> + if ((CommSize != NULL) && \ >> >> + ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize)))) >> >> + { >> >> + *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize); >> >> + return EFI_BAD_BUFFER_SIZE; >> >> + } >> >> + >> >> + CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase)); >> >> + >> >> + CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize); > [SAMI] If CommSize is NULL, the above the above line will result in a > crash, right? >> + >> >> + // CommBuffer is a mandatory parameter. Hence, Rely on >> >> + // MessageLength + Header to ascertain the >> >> + // total size of the communication payload rather than >> >> + // rely on optional CommSize parameter >> >> + BufferSize = CommunicateHeader->MessageLength + >> >> + sizeof (CommunicateHeader->HeaderGuid) + >> >> + sizeof (CommunicateHeader->MessageLength); >> >> + >> >> + // >> >> + // If CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER); >> >> + // >> >> + if ((CommSize != NULL) && (*CommSize != BufferSize)) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } > [SAMI] It may be better to do this check earlier in the code by > casting CommBuffer to EFI_MM_COMMUNICATE_HEADER * and calculating the > BufferSize. That way the CopyMem() above can be avoided if the above > test fails. >> + >> >> + // SMC Function ID >> >> + CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64; >> >> + >> >> + // Cookie >> >> + CommunicateSmcArgs.Arg1 = 0; >> >> + >> >> + // comm_buffer_address (64-bit physical address) >> >> + CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader; >> >> + >> >> + // comm_size_address (not used, indicated by setting to zero) >> >> + CommunicateSmcArgs.Arg3 = 0; >> >> + >> >> + // Call the Standalone MM environment. >> >> + ArmCallSmc (&CommunicateSmcArgs); >> >> + >> >> + switch (CommunicateSmcArgs.Arg0) { >> >> + case ARM_SMC_MM_RET_SUCCESS: >> >> + // On successful return, the size of data being returned is inferred from >> >> + // MessageLength + Header. >> >> + BufferSize = CommunicateHeader->MessageLength + >> >> + sizeof (CommunicateHeader->HeaderGuid) + >> >> + sizeof (CommunicateHeader->MessageLength); >> >> + CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize); > > [SAMI] Can there be a case where the returned MessageLength results in > the CommBuffer size being smaller, i.e. BufferSize returned > *CommSize ? > > I expect ARM_SMC_MM_RET_NO_MEMORY to have been returned in the first > place, but it may be worth adding a check to avoid potential issues. > What do you think? > >> + if (CommSize != NULL) { >> >> + *CommSize = BufferSize; >> >> + } >> >> + >> >> + Status = EFI_SUCCESS; >> >> + break; >> >> + >> >> + case ARM_SMC_MM_RET_INVALID_PARAMS: >> >> + Status = EFI_INVALID_PARAMETER; >> >> + break; >> >> + >> >> + case ARM_SMC_MM_RET_DENIED: >> >> + Status = EFI_ACCESS_DENIED; >> >> + break; >> >> + >> >> + case ARM_SMC_MM_RET_NO_MEMORY: >> >> + // Unexpected error since the CommSize was checked for zero length >> >> + // prior to issuing the SMC >> >> + Status = EFI_OUT_OF_RESOURCES; >> >> + ASSERT (0); >> >> + break; >> >> + >> >> + default: >> >> + Status = EFI_ACCESS_DENIED; >> >> + ASSERT (0); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc >> index 6b938ce8b671..4939b3d59b7f 100644 >> --- a/ArmPkg/ArmPkg.dsc >> +++ b/ArmPkg/ArmPkg.dsc >> @@ -162,6 +162,8 @@ [Components.common] >> ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf >> >> ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf >> >> >> >> + ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf >> >> + >> >> [Components.AARCH64] >> >> ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf >> >> ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf >> >> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h >> new file mode 100644 >> index 000000000000..a99baa2496a9 >> --- /dev/null >> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h >> @@ -0,0 +1,76 @@ >> +/** @file -- MmCommunicationPei.h >> >> + Provides an interface to send MM request in PEI >> >> + >> >> + Copyright (c) Microsoft Corporation. >> >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +**/ >> >> + >> >> +#ifndef MM_COMMUNICATION_PEI_H_ >> >> +#define MM_COMMUNICATION_PEI_H_ >> >> + >> >> +#include <PiPei.h> >> >> + >> >> +#include <Library/BaseLib.h> >> >> +#include <Library/BaseMemoryLib.h> >> >> +#include <Library/ArmSmcLib.h> >> >> +#include <Library/DebugLib.h> >> >> +#include <Library/PcdLib.h> >> >> +#include <Library/PeimEntryPoint.h> >> >> +#include <Library/PeiServicesLib.h> >> >> +#include <Library/HobLib.h> >> >> + >> >> +#include <Protocol/MmCommunication.h> >> >> + >> >> +#include <IndustryStandard/ArmStdSmc.h> >> >> + >> >> +#include <Ppi/MmCommunication.h> >> >> + >> >> +/** >> >> + Entry point of PEI MM Communication driver >> >> + >> >> + @param FileHandle Handle of the file being invoked. >> >> + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). >> >> + @param PeiServices General purpose services available to every PEIM. >> >> + >> >> + @retval EFI_SUCCESS If the interface could be successfully installed >> >> + @retval Others Returned from PeiServicesInstallPpi() >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +MmCommunicationPeiInitialize ( >> >> + IN EFI_PEI_FILE_HANDLE FileHandle, >> >> + IN CONST EFI_PEI_SERVICES **PeiServices >> >> + ); >> >> + >> >> +/** >> >> + MmCommunicationPeim >> >> + Communicates with a registered handler. >> >> + This function provides a service to send and receive messages from a registered UEFI service during PEI. >> >> + >> >> + @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance. >> >> + @param[in, out] CommBuffer Pointer to the data buffer >> >> + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the >> >> + size of data being returned. Zero if the handler does not >> >> + wish to reply with any data. >> >> + >> >> + @retval EFI_SUCCESS The message was successfully posted. >> >> + @retval EFI_INVALID_PARAMETER CommBuffer was NULL or *CommSize does not match >> >> + MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER). >> >> + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. >> >> + If this error is returned, the MessageLength field >> >> + in the CommBuffer header or the integer pointed by >> >> + CommSize, are updated to reflect the maximum payload >> >> + size the implementation can accommodate. >> >> + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, >> >> + if not omitted, are in address range that cannot be >> >> + accessed by the MM environment. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +MmCommunicationPeim ( >> >> + IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This, >> >> + IN OUT VOID *CommBuffer, >> >> + IN OUT UINTN *CommSize >> >> + ); >> >> + >> >> +#endif /* MM_COMMUNICATION_PEI_H_ */ >> >> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf >> new file mode 100644 >> index 000000000000..f4e359dafd75 >> --- /dev/null >> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf >> @@ -0,0 +1,41 @@ >> +## @file -- MmCommunicationPei.inf >> >> +# PEI MM Communicate driver >> >> +# >> >> +# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR> >> >> +# Copyright (c) Microsoft Corporation. >> >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +## >> >> + >> >> +[Defines] >> >> + INF_VERSION = 0x00010005 > [SAMI] The version should be |0x0001001B. See > https://github.com/tianocore-docs/edk2-InfSpecification/blob/master/3_edk_ii_inf_file_format/34_%5Bdefines%5D_section.md > | >> + BASE_NAME = MmCommunicationPei >> >> + FILE_GUID = 58FFB346-1B75-42C7-AD69-37C652423C1A >> >> + MODULE_TYPE = PEIM >> >> + VERSION_STRING = 1.0 >> >> + ENTRY_POINT = MmCommunicationPeiInitialize >> >> + >> >> +[Sources] >> >> + MmCommunicationPei.c >> >> + MmCommunicationPei.h >> >> + >> >> +[Packages] >> >> + MdePkg/MdePkg.dec >> >> + MdeModulePkg/MdeModulePkg.dec >> >> + ArmPkg/ArmPkg.dec >> >> + >> >> +[LibraryClasses] >> >> + DebugLib >> >> + ArmSmcLib >> >> + PeimEntryPoint >> >> + PeiServicesLib >> >> + HobLib >> >> + >> >> +[Pcd] >> >> + gArmTokenSpaceGuid.PcdMmBufferBase >> >> + gArmTokenSpaceGuid.PcdMmBufferSize >> >> + >> >> +[Ppis] >> >> + gEfiPeiMmCommunicationPpiGuid ## PRODUCES >> >> + >> >> +[Depex] >> >> + TRUE >> [-- Attachment #2: Type: text/html, Size: 17492 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI 2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin 2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin @ 2023-06-08 20:44 ` Kun Qin 2023-06-25 2:23 ` 回复: [edk2-devel] " gaoliming 1 sibling, 1 reply; 8+ messages in thread From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw) To: devel Cc: Hao A Wu, Liming Gao, Jian J Wang, Ronny Hansen, Shriram Masanamuthu Chinnathurai, Preshit Harlikar From: Kun Qin <kuqin@microsoft.com> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 This change introduced the Standalone MM based variable read capability in PEI phase for applicable platforms (such as ARM platforms). Similar to the x86 counterpart, MM communicate PPI is used to request variable information from Standalone MM environment. Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Jian J Wang <jian.j.wang@intel.com> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com> Co-authored-by: Shriram Masanamuthu Chinnathurai <shriramma@microsoft.com> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com> Signed-off-by: Kun Qin <kuqin@microsoft.com> --- MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c | 381 ++++++++++++++++++++ MdeModulePkg/MdeModulePkg.dsc | 1 + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h | 134 +++++++ MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf | 43 +++ 4 files changed, 559 insertions(+) diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c new file mode 100644 index 000000000000..4f937e22e89e --- /dev/null +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c @@ -0,0 +1,381 @@ +/** @file -- MmVariablePei.c + Provides interface for reading Secure System Variables during PEI. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> + Copyright (c) Microsoft Corporation.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "MmVariablePei.h" + +#define MM_VARIABLE_COMM_BUFFER_OFFSET (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) + +// +// Module globals +// +EFI_PEI_READ_ONLY_VARIABLE2_PPI mPeiSecureVariableRead = { + PeiMmGetVariable, + PeiMmGetNextVariableName +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiMmVariablePpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiReadOnlyVariable2PpiGuid, + &mPeiSecureVariableRead +}; + +/** + Entry point of PEI Secure Variable read driver + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() +**/ +EFI_STATUS +EFIAPI +PeiMmVariableInitialize ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + return PeiServicesInstallPpi (&mPeiMmVariablePpi); +} + +/** + Helper function to populate MM communicate header and variable communicate header + and then communicate to PEI. + + @param[in, out] CommunicateBuffer Size of the variable name. + @param[in] CommunicateBufferSize The entire buffer size to be sent to MM. + @param[in] Function The MM variable function value. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS Find the specified variable. + @retval Others Errors returned by MM communicate or variable service. + +**/ +EFI_STATUS +PopulateHeaderAndCommunicate ( + IN OUT UINT8 *CommunicateBuffer, + IN UINTN CommunicateBufferSize, + IN UINTN Function + ) +{ + EFI_STATUS Status; + EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi; + EFI_MM_COMMUNICATE_HEADER *MmCommunicateHeader; + SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader; + + // Minimal sanity check + if ((CommunicateBuffer == NULL) || + (CommunicateBufferSize < MM_VARIABLE_COMM_BUFFER_OFFSET)) + { + Status = EFI_INVALID_PARAMETER; + DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize)); + goto Exit; + } + + if ((Function != SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) && + (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE)) + { + Status = EFI_INVALID_PARAMETER; + DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", __func__, Function)); + goto Exit; + } + + Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, NULL, (VOID **)&MmCommunicationPpi); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication PPI: %r\n", __func__, Status)); + goto Exit; + } + + // Zero the entire Communication Buffer Header + MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommunicateBuffer; + + ZeroMem (MmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE); + + // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM + CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID)); + + // Program the MM header size + MmCommunicateHeader->MessageLength = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE; + + MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE); + + // We are only supporting GetVariable and GetNextVariableName + MmVarCommsHeader->Function = Function; + + // Send the MM request using MmCommunicationPei + Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, CommunicateBuffer, &CommunicateBufferSize); + if (EFI_ERROR (Status)) { + // Received an error from MM interface. + DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, Status)); + goto Exit; + } + + // MM request was successfully handled by the framework. + // Set status to the Variable Service Status Code + Status = MmVarCommsHeader->ReturnStatus; + if (EFI_ERROR (Status)) { + // We received an error from Variable Service. + // We cant do anymore so return Status + if (Status != EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", __func__, Status)); + } + + goto Exit; + } + +Exit: + return Status; +} + +/** + This service retrieves a variable's value using its name and GUID. + + This function is using the Secure Variable Store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer + size to obtain the data. + + @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + @param VariableName A pointer to a null-terminated string that is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of + VariableGuid and VariableName must be unique. + @param Attributes If non-NULL, on return, points to the variable's attributes. + @param DataSize On entry, points to the size in bytes of the Data buffer. + On return, points to the size of the data returned in Data. + @param Data Points to the buffer which will hold the returned variable value. + May be NULL with a zero DataSize in order to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. + DataSize is updated with the size required for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiMmGetVariable ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN MessageSize; + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *MmVarAccessHeader; + UINT8 *MmCommunicateBuffer; + UINTN RequiredPages; + + // Check input parameters + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (VariableName[0] == 0) { + return EFI_NOT_FOUND; + } + + if ((*DataSize > 0) && (Data == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Allocate required pages to send MM request + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + + StrSize (VariableName) + *DataSize; + + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); + + if (MmCommunicateBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status)); + return Status; + } + + // Zero the entire Communication Buffer + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); + + // + // Program all payload structure contents + // + MmVarAccessHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); + + // Variable GUID + CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof (GUID)); + + // Program the max amount of data we accept. + MmVarAccessHeader->DataSize = *DataSize; + + // Get size of the variable name + MmVarAccessHeader->NameSize = StrSize (VariableName); + + // Populate incoming variable name + CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, MmVarAccessHeader->NameSize); + + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); + if (EFI_ERROR (Status)) { + // We received an error from either communicate or Variable Service. + if (Status != EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status)); + } + + goto Exit; + } + + Status = EFI_SUCCESS; + + // User provided buffer is too small + if (*DataSize < MmVarAccessHeader->DataSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + +Exit: + // Check if we need to set Attributes + if (Attributes != NULL) { + *Attributes = MmVarAccessHeader->Attributes; + } + + *DataSize = MmVarAccessHeader->DataSize; + + if (Status == EFI_SUCCESS) { + CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + MmVarAccessHeader->NameSize, *DataSize); + } + + // Free the Communication Buffer + if (MmCommunicateBuffer != NULL) { + FreePages (MmCommunicateBuffer, RequiredPages); + } + + return Status; +} + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName. + On return, the size of the variable name buffer. + @param VariableName On entry, a pointer to a null-terminated string that is the variable's name. + On return, points to the next variable's null-terminated name string. + + @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. +**/ +EFI_STATUS +EFIAPI +PeiMmGetNextVariableName ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ) +{ + EFI_STATUS Status; + UINTN MessageSize; + UINT8 *MmCommunicateBuffer; + SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *MmVarGetNextVarHeader; + UINTN RequiredPages; + + // Check input parameters + if ((VariableName == NULL) || + (VariableGuid == NULL) || + (VariableNameSize == NULL) || + (*VariableNameSize == 0)) + { + return EFI_INVALID_PARAMETER; + } + + // Allocate required pages to send MM request + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + + StrSize (VariableName) + *VariableNameSize; + + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); + + if (MmCommunicateBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status)); + return Status; + } + + // Zero the entire Communication Buffer + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); + + // + // Program all payload structure contents + // + MmVarGetNextVarHeader = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); + + // Variable GUID + CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, sizeof (GUID)); + + // Program the maximal length of name we can accept. + MmVarGetNextVarHeader->NameSize = *VariableNameSize; + + // Populate incoming variable name + CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName, MmVarGetNextVarHeader->NameSize); + + // Send the MM request using MmCommunicationPei + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); + if (EFI_ERROR (Status)) { + // We received an error from either communicate or Variable Service. + if (Status != EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status)); + } + + goto Exit; + } + + Status = EFI_SUCCESS; + + // User provided buffer is too small + if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + +Exit: + // Update the name size to be returned + *VariableNameSize = MmVarGetNextVarHeader->NameSize; + + if (Status == EFI_SUCCESS) { + CopyMem ((VOID *)VariableName, (UINT8 *)MmVarGetNextVarHeader->Name, *VariableNameSize); + CopyMem ((VOID *)VariableGuid, (UINT8 *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID)); + } + + // Free the Communication Buffer + if (MmCommunicateBuffer != NULL) { + FreePages (MmCommunicateBuffer, RequiredPages); + } + + return Status; +} diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 5b1f50e9c084..1aedfe280ae1 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -400,6 +400,7 @@ [Components] MdeModulePkg/Application/VariableInfo/VariableInfo.inf MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf MdeModulePkg/Universal/Variable/Pei/VariablePei.inf + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h new file mode 100644 index 000000000000..0feed8cd1cb6 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h @@ -0,0 +1,134 @@ +/** @file -- MmVariablePei.h + Provides interface for reading Secure System Variables during PEI. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef PEI_MM_VARIABLE_LIB_H_ +#define PEI_MM_VARIABLE_LIB_H_ + +#include <PiPei.h> +#include <Uefi/UefiSpec.h> + +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/PeimEntryPoint.h> +#include <Library/PeiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/HobLib.h> + +#include <Guid/SmmVariableCommon.h> + +#include <Ppi/ReadOnlyVariable2.h> +#include <Ppi/MmCommunication.h> + +#include <Protocol/SmmVariable.h> +#include <Protocol/MmCommunication.h> + +/** + Entry point of PEI Secure Variable read driver + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() +**/ +EFI_STATUS +EFIAPI +PeiMmVariableInitialize ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + + This function enables the read of Secure Variables during PEI. + + This function is using the Secure Variable Store.If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer + size to obtain the data. + + The function performs the following: + + 1) Creates an MM request + 2) Fills out the following data structures for the Secure Variable Service + SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE + 3) Adds the MM data structures to the MM request. + 4) Sends the MM request to EL3 using MmCommunicationPeiLib. + 5) The MM request is sent to S-EL0. + 6) The MM request is then handled by the registered handler with GUID: gEfiSmmVariableProtocolGuid + + @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + @param VariableName A pointer to a null-terminated string that is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of + VariableGuid and VariableName must be unique. + @param Attributes If non-NULL, on return, points to the variable's attributes. + @param DataSize On entry, points to the size in bytes of the Data buffer. + On return, points to the size of the data returned in Data. + @param Data Points to the buffer which will hold the returned variable value. + May be NULL with a zero DataSize in order to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. + DataSize is updated with the size required for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiMmGetVariable ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName. + On return, the size of the variable name buffer. + @param VariableName On entry, a pointer to a null-terminated string that is the variable's name. + On return, points to the next variable's null-terminated name string. + + @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. +**/ +EFI_STATUS +EFIAPI +PeiMmGetNextVariableName ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ); + +#endif /* PEI_MM_VARIABLE_LIB_H_ */ diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf new file mode 100644 index 000000000000..d122703e9b5d --- /dev/null +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf @@ -0,0 +1,43 @@ +## @file -- MmVariablePei.inf +# Provides interface for reading Secure System Variables during PEI. +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MmVariablePei + FILE_GUID = CD660A87-454B-4346-A35C-3D89BF8ECFAF + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeiMmVariableInitialize + +[Sources] + MmVariablePei.c + MmVariablePei.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + PeiServicesLib + PeimEntryPoint + MemoryAllocationLib + HobLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize + +[Protocols] + gEfiSmmVariableProtocolGuid ## CONSUMES + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES + gEfiPeiMmCommunicationPpiGuid ## CONSUMES + +[Depex] + gEfiPeiMmCommunicationPpiGuid -- 2.40.1.windows.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI 2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin @ 2023-06-25 2:23 ` gaoliming 2023-06-26 20:10 ` Kun Qin 0 siblings, 1 reply; 8+ messages in thread From: gaoliming @ 2023-06-25 2:23 UTC (permalink / raw) To: devel, kuqin12 Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen', 'Shriram Masanamuthu Chinnathurai', 'Preshit Harlikar' Kun: Seemly, PcdMaxVariableSize is not used by this module. It can be removed. And, has its functionality been verified in the real platform? Thanks Liming > -----邮件原件----- > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin > 发送时间: 2023年6月9日 4:45 > 收件人: devel@edk2.groups.io > 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao > <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>; Ronny > Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu > Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar > <pharlikar@microsoft.com> > 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM > based variable read service in PEI > > From: Kun Qin <kuqin@microsoft.com> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 > > This change introduced the Standalone MM based variable read capability > in PEI phase for applicable platforms (such as ARM platforms). > > Similar to the x86 counterpart, MM communicate PPI is used to request > variable information from Standalone MM environment. > > Cc: Hao A Wu <hao.a.wu@intel.com> > Cc: Liming Gao <gaoliming@byosoft.com.cn> > Cc: Jian J Wang <jian.j.wang@intel.com> > > Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com> > Co-authored-by: Shriram Masanamuthu Chinnathurai > <shriramma@microsoft.com> > Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com> > Signed-off-by: Kun Qin <kuqin@microsoft.com> > --- > MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c | > 381 ++++++++++++++++++++ > MdeModulePkg/MdeModulePkg.dsc > | 1 + > MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h | > 134 +++++++ > MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf | > 43 +++ > 4 files changed, 559 insertions(+) > > diff --git > a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > new file mode 100644 > index 000000000000..4f937e22e89e > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > @@ -0,0 +1,381 @@ > +/** @file -- MmVariablePei.c > > + Provides interface for reading Secure System Variables during PEI. > > + > > + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> > > + Copyright (c) Microsoft Corporation.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "MmVariablePei.h" > > + > > +#define MM_VARIABLE_COMM_BUFFER_OFFSET > (SMM_COMMUNICATE_HEADER_SIZE + > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) > > + > > +// > > +// Module globals > > +// > > +EFI_PEI_READ_ONLY_VARIABLE2_PPI mPeiSecureVariableRead = { > > + PeiMmGetVariable, > > + PeiMmGetNextVariableName > > +}; > > + > > +EFI_PEI_PPI_DESCRIPTOR mPeiMmVariablePpi = { > > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > > + &gEfiPeiReadOnlyVariable2PpiGuid, > > + &mPeiSecureVariableRead > > +}; > > + > > +/** > > + Entry point of PEI Secure Variable read driver > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in > FfsFindNextFile(). > > + @param PeiServices General purpose services available to every > PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmVariableInitialize ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ) > > +{ > > + return PeiServicesInstallPpi (&mPeiMmVariablePpi); > > +} > > + > > +/** > > + Helper function to populate MM communicate header and variable > communicate header > > + and then communicate to PEI. > > + > > + @param[in, out] CommunicateBuffer Size of the variable name. > > + @param[in] CommunicateBufferSize The entire buffer size to be > sent to MM. > > + @param[in] Function The MM variable function > value. > > + > > + @retval EFI_INVALID_PARAMETER Invalid parameter. > > + @retval EFI_SUCCESS Find the specified variable. > > + @retval Others Errors returned by MM > communicate or variable service. > > + > > +**/ > > +EFI_STATUS > > +PopulateHeaderAndCommunicate ( > > + IN OUT UINT8 *CommunicateBuffer, > > + IN UINTN CommunicateBufferSize, > > + IN UINTN Function > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi; > > + EFI_MM_COMMUNICATE_HEADER *MmCommunicateHeader; > > + SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader; > > + > > + // Minimal sanity check > > + if ((CommunicateBuffer == NULL) || > > + (CommunicateBufferSize < > MM_VARIABLE_COMM_BUFFER_OFFSET)) > > + { > > + Status = EFI_INVALID_PARAMETER; > > + DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and > 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize)); > > + goto Exit; > > + } > > + > > + if ((Function != > SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) && > > + (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE)) > > + { > > + Status = EFI_INVALID_PARAMETER; > > + DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", > __func__, Function)); > > + goto Exit; > > + } > > + > > + Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, > NULL, (VOID **)&MmCommunicationPpi); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication > PPI: %r\n", __func__, Status)); > > + goto Exit; > > + } > > + > > + // Zero the entire Communication Buffer Header > > + MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER > *)CommunicateBuffer; > > + > > + ZeroMem (MmCommunicateHeader, > SMM_COMMUNICATE_HEADER_SIZE); > > + > > + // Use gEfiSmmVariableProtocolGuid to request the MM variable service > in Standalone MM > > + CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, > &gEfiSmmVariableProtocolGuid, sizeof (GUID)); > > + > > + // Program the MM header size > > + MmCommunicateHeader->MessageLength = CommunicateBufferSize - > SMM_COMMUNICATE_HEADER_SIZE; > > + > > + MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER > *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE); > > + > > + // We are only supporting GetVariable and GetNextVariableName > > + MmVarCommsHeader->Function = Function; > > + > > + // Send the MM request using MmCommunicationPei > > + Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, > CommunicateBuffer, &CommunicateBufferSize); > > + if (EFI_ERROR (Status)) { > > + // Received an error from MM interface. > > + DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, > Status)); > > + goto Exit; > > + } > > + > > + // MM request was successfully handled by the framework. > > + // Set status to the Variable Service Status Code > > + Status = MmVarCommsHeader->ReturnStatus; > > + if (EFI_ERROR (Status)) { > > + // We received an error from Variable Service. > > + // We cant do anymore so return Status > > + if (Status != EFI_BUFFER_TOO_SMALL) { > > + DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", > __func__, Status)); > > + } > > + > > + goto Exit; > > + } > > + > > +Exit: > > + return Status; > > +} > > + > > +/** > > + This service retrieves a variable's value using its name and GUID. > > + > > + This function is using the Secure Variable Store. If the Data > > + buffer is too small to hold the contents of the variable, the error > > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required > buffer > > + size to obtain the data. > > + > > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > > + @param VariableName A pointer to a null-terminated string > that is the variable's name. > > + @param VariableGuid A pointer to an EFI_GUID that is the > variable's GUID. The combination of > > + VariableGuid and VariableName > must be unique. > > + @param Attributes If non-NULL, on return, points to the > variable's attributes. > > + @param DataSize On entry, points to the size in bytes > of the Data buffer. > > + On return, points to the size of the > data returned in Data. > > + @param Data Points to the buffer which will hold > the returned variable value. > > + May be NULL with a zero DataSize in > order to determine the size of the buffer needed. > > + > > + @retval EFI_SUCCESS The variable was read successfully. > > + @retval EFI_NOT_FOUND The variable was not found. > > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the > resulting data. > > + DataSize is updated with the size > required for > > + the specified variable. > > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize > or Data is NULL. > > + @retval EFI_DEVICE_ERROR The variable could not be retrieved > because of a device error. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmGetVariable ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VariableGuid, > > + OUT UINT32 *Attributes, OPTIONAL > > + IN OUT UINTN *DataSize, > > + OUT VOID *Data OPTIONAL > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN MessageSize; > > + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > *MmVarAccessHeader; > > + UINT8 > *MmCommunicateBuffer; > > + UINTN RequiredPages; > > + > > + // Check input parameters > > + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == > NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (VariableName[0] == 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + if ((*DataSize > 0) && (Data == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Allocate required pages to send MM request > > + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + > > + OFFSET_OF > (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + > > + StrSize (VariableName) + *DataSize; > > + > > + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); > > + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); > > + > > + if (MmCommunicateBuffer == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", > __func__, Status)); > > + return Status; > > + } > > + > > + // Zero the entire Communication Buffer > > + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); > > + > > + // > > + // Program all payload structure contents > > + // > > + MmVarAccessHeader = > (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); > > + > > + // Variable GUID > > + CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof > (GUID)); > > + > > + // Program the max amount of data we accept. > > + MmVarAccessHeader->DataSize = *DataSize; > > + > > + // Get size of the variable name > > + MmVarAccessHeader->NameSize = StrSize (VariableName); > > + > > + // Populate incoming variable name > > + CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, > MmVarAccessHeader->NameSize); > > + > > + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, > MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); > > + if (EFI_ERROR (Status)) { > > + // We received an error from either communicate or Variable Service. > > + if (Status != EFI_BUFFER_TOO_SMALL) { > > + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable > service errored: %r\n", __func__, Status)); > > + } > > + > > + goto Exit; > > + } > > + > > + Status = EFI_SUCCESS; > > + > > + // User provided buffer is too small > > + if (*DataSize < MmVarAccessHeader->DataSize) { > > + Status = EFI_BUFFER_TOO_SMALL; > > + } > > + > > +Exit: > > + // Check if we need to set Attributes > > + if (Attributes != NULL) { > > + *Attributes = MmVarAccessHeader->Attributes; > > + } > > + > > + *DataSize = MmVarAccessHeader->DataSize; > > + > > + if (Status == EFI_SUCCESS) { > > + CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + > MmVarAccessHeader->NameSize, *DataSize); > > + } > > + > > + // Free the Communication Buffer > > + if (MmCommunicateBuffer != NULL) { > > + FreePages (MmCommunicateBuffer, RequiredPages); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Return the next variable name and GUID. > > + > > + This function is called multiple times to retrieve the VariableName > > + and VariableGuid of all variables currently available in the system. > > + On each call, the previous results are passed into the interface, > > + and, on return, the interface returns the data for the next > > + interface. When the entire variable list has been returned, > > + EFI_NOT_FOUND is returned. > > + > > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > > + > > + @param VariableNameSize On entry, points to the size of the buffer > pointed to by VariableName. > > + On return, the size of the variable name > buffer. > > + @param VariableName On entry, a pointer to a null-terminated > string that is the variable's name. > > + On return, points to the next variable's > null-terminated name string. > > + > > + @param VariableGuid On entry, a pointer to an EFI_GUID that is > the variable's GUID. > > + On return, a pointer to the next variable's > GUID. > > + > > + @retval EFI_SUCCESS The variable was read successfully. > > + @retval EFI_NOT_FOUND The variable could not be found. > > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small > for the resulting > > + data. VariableNameSize is updated > with the size > > + required for the specified variable. > > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > > + VariableNameSize is NULL. > > + @retval EFI_DEVICE_ERROR The variable could not be retrieved > because of a device error. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmGetNextVariableName ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN OUT UINTN *VariableNameSize, > > + IN OUT CHAR16 *VariableName, > > + IN OUT EFI_GUID *VariableGuid > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN > MessageSize; > > + UINT8 > *MmCommunicateBuffer; > > + SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > *MmVarGetNextVarHeader; > > + UINTN > RequiredPages; > > + > > + // Check input parameters > > + if ((VariableName == NULL) || > > + (VariableGuid == NULL) || > > + (VariableNameSize == NULL) || > > + (*VariableNameSize == 0)) > > + { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Allocate required pages to send MM request > > + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + > > + OFFSET_OF > (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + > > + StrSize (VariableName) + *VariableNameSize; > > + > > + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); > > + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); > > + > > + if (MmCommunicateBuffer == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", > __func__, Status)); > > + return Status; > > + } > > + > > + // Zero the entire Communication Buffer > > + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); > > + > > + // > > + // Program all payload structure contents > > + // > > + MmVarGetNextVarHeader = > (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); > > + > > + // Variable GUID > > + CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, > sizeof (GUID)); > > + > > + // Program the maximal length of name we can accept. > > + MmVarGetNextVarHeader->NameSize = *VariableNameSize; > > + > > + // Populate incoming variable name > > + CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName, > MmVarGetNextVarHeader->NameSize); > > + > > + // Send the MM request using MmCommunicationPei > > + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, > MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); > > + if (EFI_ERROR (Status)) { > > + // We received an error from either communicate or Variable Service. > > + if (Status != EFI_BUFFER_TOO_SMALL) { > > + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable > service errored: %r\n", __func__, Status)); > > + } > > + > > + goto Exit; > > + } > > + > > + Status = EFI_SUCCESS; > > + > > + // User provided buffer is too small > > + if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) { > > + Status = EFI_BUFFER_TOO_SMALL; > > + } > > + > > +Exit: > > + // Update the name size to be returned > > + *VariableNameSize = MmVarGetNextVarHeader->NameSize; > > + > > + if (Status == EFI_SUCCESS) { > > + CopyMem ((VOID *)VariableName, (UINT8 > *)MmVarGetNextVarHeader->Name, *VariableNameSize); > > + CopyMem ((VOID *)VariableGuid, (UINT8 > *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID)); > > + } > > + > > + // Free the Communication Buffer > > + if (MmCommunicateBuffer != NULL) { > > + FreePages (MmCommunicateBuffer, RequiredPages); > > + } > > + > > + return Status; > > +} > > diff --git a/MdeModulePkg/MdeModulePkg.dsc > b/MdeModulePkg/MdeModulePkg.dsc > index 5b1f50e9c084..1aedfe280ae1 100644 > --- a/MdeModulePkg/MdeModulePkg.dsc > +++ b/MdeModulePkg/MdeModulePkg.dsc > @@ -400,6 +400,7 @@ [Components] > MdeModulePkg/Application/VariableInfo/VariableInfo.inf > > > MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf > > MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > > + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > > MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf > > MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf > > > MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > > diff --git > a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > new file mode 100644 > index 000000000000..0feed8cd1cb6 > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > @@ -0,0 +1,134 @@ > +/** @file -- MmVariablePei.h > > + Provides interface for reading Secure System Variables during PEI. > > + > > + Copyright (c) Microsoft Corporation. > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef PEI_MM_VARIABLE_LIB_H_ > > +#define PEI_MM_VARIABLE_LIB_H_ > > + > > +#include <PiPei.h> > > +#include <Uefi/UefiSpec.h> > > + > > +#include <Library/DebugLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/PeimEntryPoint.h> > > +#include <Library/PeiServicesLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/HobLib.h> > > + > > +#include <Guid/SmmVariableCommon.h> > > + > > +#include <Ppi/ReadOnlyVariable2.h> > > +#include <Ppi/MmCommunication.h> > > + > > +#include <Protocol/SmmVariable.h> > > +#include <Protocol/MmCommunication.h> > > + > > +/** > > + Entry point of PEI Secure Variable read driver > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in > FfsFindNextFile(). > > + @param PeiServices General purpose services available to every > PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmVariableInitialize ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ); > > + > > +/** > > + > > + This function enables the read of Secure Variables during PEI. > > + > > + This function is using the Secure Variable Store.If the Data > > + buffer is too small to hold the contents of the variable, the error > > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required > buffer > > + size to obtain the data. > > + > > + The function performs the following: > > + > > + 1) Creates an MM request > > + 2) Fills out the following data structures for the Secure Variable Service > > + > SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT > E_ACCESS_VARIABLE > > + 3) Adds the MM data structures to the MM request. > > + 4) Sends the MM request to EL3 using MmCommunicationPeiLib. > > + 5) The MM request is sent to S-EL0. > > + 6) The MM request is then handled by the registered handler with GUID: > gEfiSmmVariableProtocolGuid > > + > > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > > + @param VariableName A pointer to a null-terminated string > that is the variable's name. > > + @param VariableGuid A pointer to an EFI_GUID that is the > variable's GUID. The combination of > > + VariableGuid and VariableName > must be unique. > > + @param Attributes If non-NULL, on return, points to the > variable's attributes. > > + @param DataSize On entry, points to the size in bytes > of the Data buffer. > > + On return, points to the size of the > data returned in Data. > > + @param Data Points to the buffer which will hold > the returned variable value. > > + May be NULL with a zero DataSize in > order to determine the size of the buffer needed. > > + > > + @retval EFI_SUCCESS The variable was read successfully. > > + @retval EFI_NOT_FOUND The variable was not found. > > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the > resulting data. > > + DataSize is updated with the size > required for > > + the specified variable. > > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize > or Data is NULL. > > + @retval EFI_DEVICE_ERROR The variable could not be retrieved > because of a device error. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmGetVariable ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VariableGuid, > > + OUT UINT32 *Attributes, > > + IN OUT UINTN *DataSize, > > + OUT VOID *Data OPTIONAL > > + ); > > + > > +/** > > + Return the next variable name and GUID. > > + > > + This function is called multiple times to retrieve the VariableName > > + and VariableGuid of all variables currently available in the system. > > + On each call, the previous results are passed into the interface, > > + and, on return, the interface returns the data for the next > > + interface. When the entire variable list has been returned, > > + EFI_NOT_FOUND is returned. > > + > > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > > + > > + @param VariableNameSize On entry, points to the size of the buffer > pointed to by VariableName. > > + On return, the size of the variable name > buffer. > > + @param VariableName On entry, a pointer to a null-terminated > string that is the variable's name. > > + On return, points to the next variable's > null-terminated name string. > > + > > + @param VariableGuid On entry, a pointer to an EFI_GUID that is > the variable's GUID. > > + On return, a pointer to the next variable's > GUID. > > + > > + @retval EFI_SUCCESS The variable was read successfully. > > + @retval EFI_NOT_FOUND The variable could not be found. > > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small > for the resulting > > + data. VariableNameSize is updated > with the size > > + required for the specified variable. > > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > > + VariableNameSize is NULL. > > + @retval EFI_DEVICE_ERROR The variable could not be retrieved > because of a device error. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiMmGetNextVariableName ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN OUT UINTN *VariableNameSize, > > + IN OUT CHAR16 *VariableName, > > + IN OUT EFI_GUID *VariableGuid > > + ); > > + > > +#endif /* PEI_MM_VARIABLE_LIB_H_ */ > > diff --git > a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > new file mode 100644 > index 000000000000..d122703e9b5d > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > @@ -0,0 +1,43 @@ > +## @file -- MmVariablePei.inf > > +# Provides interface for reading Secure System Variables during PEI. > > +# > > +# Copyright (c) Microsoft Corporation. > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = MmVariablePei > > + FILE_GUID = > CD660A87-454B-4346-A35C-3D89BF8ECFAF > > + MODULE_TYPE = PEIM > > + VERSION_STRING = 1.0 > > + ENTRY_POINT = PeiMmVariableInitialize > > + > > +[Sources] > > + MmVariablePei.c > > + MmVariablePei.h > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + > > +[LibraryClasses] > > + PcdLib > > + PeiServicesLib > > + PeimEntryPoint > > + MemoryAllocationLib > > + HobLib > > + > > +[Pcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize > > + > > +[Protocols] > > + gEfiSmmVariableProtocolGuid ## CONSUMES > > + > > +[Ppis] > > + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES > > + gEfiPeiMmCommunicationPpiGuid ## CONSUMES > > + > > +[Depex] > > + gEfiPeiMmCommunicationPpiGuid > > -- > 2.40.1.windows.1 > > > > -=-=-=-=-=-= > Groups.io Links: You receive all messages sent to this group. > View/Reply Online (#105956): > https://edk2.groups.io/g/devel/message/105956 > Mute This Topic: https://groups.io/mt/99415826/4905953 > Group Owner: devel+owner@edk2.groups.io > Unsubscribe: https://edk2.groups.io/g/devel/unsub > [gaoliming@byosoft.com.cn] > -=-=-=-=-=-= > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI 2023-06-25 2:23 ` 回复: [edk2-devel] " gaoliming @ 2023-06-26 20:10 ` Kun Qin 2023-06-27 0:53 ` 回复: " gaoliming 0 siblings, 1 reply; 8+ messages in thread From: Kun Qin @ 2023-06-26 20:10 UTC (permalink / raw) To: devel, gaoliming Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen', 'Shriram Masanamuthu Chinnathurai', 'Preshit Harlikar' Hi Liming, Thanks for catching that. I have removed the PCD usage and resend the patch here: https://edk2.groups.io/g/devel/message/106372 Could you please let me know if you have any other feedback? Per your functionality question, yes, the functionality was verified on both virtual and physical ARM platforms. I also added this statement to the v2 cover letter. Thanks, Kun On 6/24/2023 7:23 PM, gaoliming via groups.io wrote: > Kun: > Seemly, PcdMaxVariableSize is not used by this module. It can be removed. > > And, has its functionality been verified in the real platform? > > Thanks > Liming >> -----邮件原件----- >> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin >> 发送时间: 2023年6月9日 4:45 >> 收件人: devel@edk2.groups.io >> 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao >> <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>; Ronny >> Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu >> Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar >> <pharlikar@microsoft.com> >> 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM >> based variable read service in PEI >> >> From: Kun Qin <kuqin@microsoft.com> >> >> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 >> >> This change introduced the Standalone MM based variable read capability >> in PEI phase for applicable platforms (such as ARM platforms). >> >> Similar to the x86 counterpart, MM communicate PPI is used to request >> variable information from Standalone MM environment. >> >> Cc: Hao A Wu <hao.a.wu@intel.com> >> Cc: Liming Gao <gaoliming@byosoft.com.cn> >> Cc: Jian J Wang <jian.j.wang@intel.com> >> >> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com> >> Co-authored-by: Shriram Masanamuthu Chinnathurai >> <shriramma@microsoft.com> >> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com> >> Signed-off-by: Kun Qin <kuqin@microsoft.com> >> --- >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c | >> 381 ++++++++++++++++++++ >> MdeModulePkg/MdeModulePkg.dsc >> | 1 + >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h | >> 134 +++++++ >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf | >> 43 +++ >> 4 files changed, 559 insertions(+) >> >> diff --git >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c >> new file mode 100644 >> index 000000000000..4f937e22e89e >> --- /dev/null >> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c >> @@ -0,0 +1,381 @@ >> +/** @file -- MmVariablePei.c >> >> + Provides interface for reading Secure System Variables during PEI. >> >> + >> >> + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> >> >> + Copyright (c) Microsoft Corporation.<BR> >> >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +**/ >> >> + >> >> +#include "MmVariablePei.h" >> >> + >> >> +#define MM_VARIABLE_COMM_BUFFER_OFFSET >> (SMM_COMMUNICATE_HEADER_SIZE + >> SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) >> >> + >> >> +// >> >> +// Module globals >> >> +// >> >> +EFI_PEI_READ_ONLY_VARIABLE2_PPI mPeiSecureVariableRead = { >> >> + PeiMmGetVariable, >> >> + PeiMmGetNextVariableName >> >> +}; >> >> + >> >> +EFI_PEI_PPI_DESCRIPTOR mPeiMmVariablePpi = { >> >> + (EFI_PEI_PPI_DESCRIPTOR_PPI | >> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), >> >> + &gEfiPeiReadOnlyVariable2PpiGuid, >> >> + &mPeiSecureVariableRead >> >> +}; >> >> + >> >> +/** >> >> + Entry point of PEI Secure Variable read driver >> >> + >> >> + @param FileHandle Handle of the file being invoked. >> >> + Type EFI_PEI_FILE_HANDLE is defined in >> FfsFindNextFile(). >> >> + @param PeiServices General purpose services available to every >> PEIM. >> >> + >> >> + @retval EFI_SUCCESS If the interface could be successfully installed >> >> + @retval Others Returned from PeiServicesInstallPpi() >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmVariableInitialize ( >> >> + IN EFI_PEI_FILE_HANDLE FileHandle, >> >> + IN CONST EFI_PEI_SERVICES **PeiServices >> >> + ) >> >> +{ >> >> + return PeiServicesInstallPpi (&mPeiMmVariablePpi); >> >> +} >> >> + >> >> +/** >> >> + Helper function to populate MM communicate header and variable >> communicate header >> >> + and then communicate to PEI. >> >> + >> >> + @param[in, out] CommunicateBuffer Size of the variable name. >> >> + @param[in] CommunicateBufferSize The entire buffer size to be >> sent to MM. >> >> + @param[in] Function The MM variable function >> value. >> >> + >> >> + @retval EFI_INVALID_PARAMETER Invalid parameter. >> >> + @retval EFI_SUCCESS Find the specified variable. >> >> + @retval Others Errors returned by MM >> communicate or variable service. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +PopulateHeaderAndCommunicate ( >> >> + IN OUT UINT8 *CommunicateBuffer, >> >> + IN UINTN CommunicateBufferSize, >> >> + IN UINTN Function >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi; >> >> + EFI_MM_COMMUNICATE_HEADER *MmCommunicateHeader; >> >> + SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader; >> >> + >> >> + // Minimal sanity check >> >> + if ((CommunicateBuffer == NULL) || >> >> + (CommunicateBufferSize < >> MM_VARIABLE_COMM_BUFFER_OFFSET)) >> >> + { >> >> + Status = EFI_INVALID_PARAMETER; >> >> + DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and >> 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize)); >> >> + goto Exit; >> >> + } >> >> + >> >> + if ((Function != >> SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) && >> >> + (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE)) >> >> + { >> >> + Status = EFI_INVALID_PARAMETER; >> >> + DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", >> __func__, Function)); >> >> + goto Exit; >> >> + } >> >> + >> >> + Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, >> NULL, (VOID **)&MmCommunicationPpi); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication >> PPI: %r\n", __func__, Status)); >> >> + goto Exit; >> >> + } >> >> + >> >> + // Zero the entire Communication Buffer Header >> >> + MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER >> *)CommunicateBuffer; >> >> + >> >> + ZeroMem (MmCommunicateHeader, >> SMM_COMMUNICATE_HEADER_SIZE); >> >> + >> >> + // Use gEfiSmmVariableProtocolGuid to request the MM variable service >> in Standalone MM >> >> + CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, >> &gEfiSmmVariableProtocolGuid, sizeof (GUID)); >> >> + >> >> + // Program the MM header size >> >> + MmCommunicateHeader->MessageLength = CommunicateBufferSize - >> SMM_COMMUNICATE_HEADER_SIZE; >> >> + >> >> + MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER >> *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE); >> >> + >> >> + // We are only supporting GetVariable and GetNextVariableName >> >> + MmVarCommsHeader->Function = Function; >> >> + >> >> + // Send the MM request using MmCommunicationPei >> >> + Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, >> CommunicateBuffer, &CommunicateBufferSize); >> >> + if (EFI_ERROR (Status)) { >> >> + // Received an error from MM interface. >> >> + DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, >> Status)); >> >> + goto Exit; >> >> + } >> >> + >> >> + // MM request was successfully handled by the framework. >> >> + // Set status to the Variable Service Status Code >> >> + Status = MmVarCommsHeader->ReturnStatus; >> >> + if (EFI_ERROR (Status)) { >> >> + // We received an error from Variable Service. >> >> + // We cant do anymore so return Status >> >> + if (Status != EFI_BUFFER_TOO_SMALL) { >> >> + DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", >> __func__, Status)); >> >> + } >> >> + >> >> + goto Exit; >> >> + } >> >> + >> >> +Exit: >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This service retrieves a variable's value using its name and GUID. >> >> + >> >> + This function is using the Secure Variable Store. If the Data >> >> + buffer is too small to hold the contents of the variable, the error >> >> + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required >> buffer >> >> + size to obtain the data. >> >> + >> >> + @param This A pointer to this instance of the >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. >> >> + @param VariableName A pointer to a null-terminated string >> that is the variable's name. >> >> + @param VariableGuid A pointer to an EFI_GUID that is the >> variable's GUID. The combination of >> >> + VariableGuid and VariableName >> must be unique. >> >> + @param Attributes If non-NULL, on return, points to the >> variable's attributes. >> >> + @param DataSize On entry, points to the size in bytes >> of the Data buffer. >> >> + On return, points to the size of the >> data returned in Data. >> >> + @param Data Points to the buffer which will hold >> the returned variable value. >> >> + May be NULL with a zero DataSize in >> order to determine the size of the buffer needed. >> >> + >> >> + @retval EFI_SUCCESS The variable was read successfully. >> >> + @retval EFI_NOT_FOUND The variable was not found. >> >> + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the >> resulting data. >> >> + DataSize is updated with the size >> required for >> >> + the specified variable. >> >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize >> or Data is NULL. >> >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved >> because of a device error. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmGetVariable ( >> >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, >> >> + IN CONST CHAR16 *VariableName, >> >> + IN CONST EFI_GUID *VariableGuid, >> >> + OUT UINT32 *Attributes, OPTIONAL >> >> + IN OUT UINTN *DataSize, >> >> + OUT VOID *Data OPTIONAL >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN MessageSize; >> >> + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE >> *MmVarAccessHeader; >> >> + UINT8 >> *MmCommunicateBuffer; >> >> + UINTN RequiredPages; >> >> + >> >> + // Check input parameters >> >> + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == >> NULL)) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (VariableName[0] == 0) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + >> >> + if ((*DataSize > 0) && (Data == NULL)) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // Allocate required pages to send MM request >> >> + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + >> >> + OFFSET_OF >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + >> >> + StrSize (VariableName) + *DataSize; >> >> + >> >> + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); >> >> + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); >> >> + >> >> + if (MmCommunicateBuffer == NULL) { >> >> + Status = EFI_OUT_OF_RESOURCES; >> >> + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", >> __func__, Status)); >> >> + return Status; >> >> + } >> >> + >> >> + // Zero the entire Communication Buffer >> >> + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); >> >> + >> >> + // >> >> + // Program all payload structure contents >> >> + // >> >> + MmVarAccessHeader = >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); >> >> + >> >> + // Variable GUID >> >> + CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof >> (GUID)); >> >> + >> >> + // Program the max amount of data we accept. >> >> + MmVarAccessHeader->DataSize = *DataSize; >> >> + >> >> + // Get size of the variable name >> >> + MmVarAccessHeader->NameSize = StrSize (VariableName); >> >> + >> >> + // Populate incoming variable name >> >> + CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, >> MmVarAccessHeader->NameSize); >> >> + >> >> + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, >> MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); >> >> + if (EFI_ERROR (Status)) { >> >> + // We received an error from either communicate or Variable Service. >> >> + if (Status != EFI_BUFFER_TOO_SMALL) { >> >> + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable >> service errored: %r\n", __func__, Status)); >> >> + } >> >> + >> >> + goto Exit; >> >> + } >> >> + >> >> + Status = EFI_SUCCESS; >> >> + >> >> + // User provided buffer is too small >> >> + if (*DataSize < MmVarAccessHeader->DataSize) { >> >> + Status = EFI_BUFFER_TOO_SMALL; >> >> + } >> >> + >> >> +Exit: >> >> + // Check if we need to set Attributes >> >> + if (Attributes != NULL) { >> >> + *Attributes = MmVarAccessHeader->Attributes; >> >> + } >> >> + >> >> + *DataSize = MmVarAccessHeader->DataSize; >> >> + >> >> + if (Status == EFI_SUCCESS) { >> >> + CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + >> MmVarAccessHeader->NameSize, *DataSize); >> >> + } >> >> + >> >> + // Free the Communication Buffer >> >> + if (MmCommunicateBuffer != NULL) { >> >> + FreePages (MmCommunicateBuffer, RequiredPages); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Return the next variable name and GUID. >> >> + >> >> + This function is called multiple times to retrieve the VariableName >> >> + and VariableGuid of all variables currently available in the system. >> >> + On each call, the previous results are passed into the interface, >> >> + and, on return, the interface returns the data for the next >> >> + interface. When the entire variable list has been returned, >> >> + EFI_NOT_FOUND is returned. >> >> + >> >> + @param This A pointer to this instance of the >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. >> >> + >> >> + @param VariableNameSize On entry, points to the size of the buffer >> pointed to by VariableName. >> >> + On return, the size of the variable name >> buffer. >> >> + @param VariableName On entry, a pointer to a null-terminated >> string that is the variable's name. >> >> + On return, points to the next variable's >> null-terminated name string. >> >> + >> >> + @param VariableGuid On entry, a pointer to an EFI_GUID that is >> the variable's GUID. >> >> + On return, a pointer to the next variable's >> GUID. >> >> + >> >> + @retval EFI_SUCCESS The variable was read successfully. >> >> + @retval EFI_NOT_FOUND The variable could not be found. >> >> + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small >> for the resulting >> >> + data. VariableNameSize is updated >> with the size >> >> + required for the specified variable. >> >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or >> >> + VariableNameSize is NULL. >> >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved >> because of a device error. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmGetNextVariableName ( >> >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, >> >> + IN OUT UINTN *VariableNameSize, >> >> + IN OUT CHAR16 *VariableName, >> >> + IN OUT EFI_GUID *VariableGuid >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN >> MessageSize; >> >> + UINT8 >> *MmCommunicateBuffer; >> >> + SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME >> *MmVarGetNextVarHeader; >> >> + UINTN >> RequiredPages; >> >> + >> >> + // Check input parameters >> >> + if ((VariableName == NULL) || >> >> + (VariableGuid == NULL) || >> >> + (VariableNameSize == NULL) || >> >> + (*VariableNameSize == 0)) >> >> + { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // Allocate required pages to send MM request >> >> + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + >> >> + OFFSET_OF >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + >> >> + StrSize (VariableName) + *VariableNameSize; >> >> + >> >> + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); >> >> + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); >> >> + >> >> + if (MmCommunicateBuffer == NULL) { >> >> + Status = EFI_OUT_OF_RESOURCES; >> >> + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", >> __func__, Status)); >> >> + return Status; >> >> + } >> >> + >> >> + // Zero the entire Communication Buffer >> >> + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); >> >> + >> >> + // >> >> + // Program all payload structure contents >> >> + // >> >> + MmVarGetNextVarHeader = >> (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); >> >> + >> >> + // Variable GUID >> >> + CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, >> sizeof (GUID)); >> >> + >> >> + // Program the maximal length of name we can accept. >> >> + MmVarGetNextVarHeader->NameSize = *VariableNameSize; >> >> + >> >> + // Populate incoming variable name >> >> + CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName, >> MmVarGetNextVarHeader->NameSize); >> >> + >> >> + // Send the MM request using MmCommunicationPei >> >> + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, >> MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); >> >> + if (EFI_ERROR (Status)) { >> >> + // We received an error from either communicate or Variable Service. >> >> + if (Status != EFI_BUFFER_TOO_SMALL) { >> >> + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable >> service errored: %r\n", __func__, Status)); >> >> + } >> >> + >> >> + goto Exit; >> >> + } >> >> + >> >> + Status = EFI_SUCCESS; >> >> + >> >> + // User provided buffer is too small >> >> + if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) { >> >> + Status = EFI_BUFFER_TOO_SMALL; >> >> + } >> >> + >> >> +Exit: >> >> + // Update the name size to be returned >> >> + *VariableNameSize = MmVarGetNextVarHeader->NameSize; >> >> + >> >> + if (Status == EFI_SUCCESS) { >> >> + CopyMem ((VOID *)VariableName, (UINT8 >> *)MmVarGetNextVarHeader->Name, *VariableNameSize); >> >> + CopyMem ((VOID *)VariableGuid, (UINT8 >> *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID)); >> >> + } >> >> + >> >> + // Free the Communication Buffer >> >> + if (MmCommunicateBuffer != NULL) { >> >> + FreePages (MmCommunicateBuffer, RequiredPages); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> diff --git a/MdeModulePkg/MdeModulePkg.dsc >> b/MdeModulePkg/MdeModulePkg.dsc >> index 5b1f50e9c084..1aedfe280ae1 100644 >> --- a/MdeModulePkg/MdeModulePkg.dsc >> +++ b/MdeModulePkg/MdeModulePkg.dsc >> @@ -400,6 +400,7 @@ [Components] >> MdeModulePkg/Application/VariableInfo/VariableInfo.inf >> >> >> MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf >> >> MdeModulePkg/Universal/Variable/Pei/VariablePei.inf >> >> + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf >> >> MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf >> >> MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf >> >> >> MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf >> >> diff --git >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h >> new file mode 100644 >> index 000000000000..0feed8cd1cb6 >> --- /dev/null >> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h >> @@ -0,0 +1,134 @@ >> +/** @file -- MmVariablePei.h >> >> + Provides interface for reading Secure System Variables during PEI. >> >> + >> >> + Copyright (c) Microsoft Corporation. >> >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +**/ >> >> + >> >> +#ifndef PEI_MM_VARIABLE_LIB_H_ >> >> +#define PEI_MM_VARIABLE_LIB_H_ >> >> + >> >> +#include <PiPei.h> >> >> +#include <Uefi/UefiSpec.h> >> >> + >> >> +#include <Library/DebugLib.h> >> >> +#include <Library/PcdLib.h> >> >> +#include <Library/BaseMemoryLib.h> >> >> +#include <Library/PeimEntryPoint.h> >> >> +#include <Library/PeiServicesLib.h> >> >> +#include <Library/MemoryAllocationLib.h> >> >> +#include <Library/HobLib.h> >> >> + >> >> +#include <Guid/SmmVariableCommon.h> >> >> + >> >> +#include <Ppi/ReadOnlyVariable2.h> >> >> +#include <Ppi/MmCommunication.h> >> >> + >> >> +#include <Protocol/SmmVariable.h> >> >> +#include <Protocol/MmCommunication.h> >> >> + >> >> +/** >> >> + Entry point of PEI Secure Variable read driver >> >> + >> >> + @param FileHandle Handle of the file being invoked. >> >> + Type EFI_PEI_FILE_HANDLE is defined in >> FfsFindNextFile(). >> >> + @param PeiServices General purpose services available to every >> PEIM. >> >> + >> >> + @retval EFI_SUCCESS If the interface could be successfully installed >> >> + @retval Others Returned from PeiServicesInstallPpi() >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmVariableInitialize ( >> >> + IN EFI_PEI_FILE_HANDLE FileHandle, >> >> + IN CONST EFI_PEI_SERVICES **PeiServices >> >> + ); >> >> + >> >> +/** >> >> + >> >> + This function enables the read of Secure Variables during PEI. >> >> + >> >> + This function is using the Secure Variable Store.If the Data >> >> + buffer is too small to hold the contents of the variable, the error >> >> + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required >> buffer >> >> + size to obtain the data. >> >> + >> >> + The function performs the following: >> >> + >> >> + 1) Creates an MM request >> >> + 2) Fills out the following data structures for the Secure Variable > Service >> + >> SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT >> E_ACCESS_VARIABLE >> >> + 3) Adds the MM data structures to the MM request. >> >> + 4) Sends the MM request to EL3 using MmCommunicationPeiLib. >> >> + 5) The MM request is sent to S-EL0. >> >> + 6) The MM request is then handled by the registered handler with GUID: >> gEfiSmmVariableProtocolGuid >> >> + >> >> + @param This A pointer to this instance of the >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. >> >> + @param VariableName A pointer to a null-terminated string >> that is the variable's name. >> >> + @param VariableGuid A pointer to an EFI_GUID that is the >> variable's GUID. The combination of >> >> + VariableGuid and VariableName >> must be unique. >> >> + @param Attributes If non-NULL, on return, points to the >> variable's attributes. >> >> + @param DataSize On entry, points to the size in bytes >> of the Data buffer. >> >> + On return, points to the size of the >> data returned in Data. >> >> + @param Data Points to the buffer which will hold >> the returned variable value. >> >> + May be NULL with a zero DataSize in >> order to determine the size of the buffer needed. >> >> + >> >> + @retval EFI_SUCCESS The variable was read successfully. >> >> + @retval EFI_NOT_FOUND The variable was not found. >> >> + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the >> resulting data. >> >> + DataSize is updated with the size >> required for >> >> + the specified variable. >> >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize >> or Data is NULL. >> >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved >> because of a device error. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmGetVariable ( >> >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, >> >> + IN CONST CHAR16 *VariableName, >> >> + IN CONST EFI_GUID *VariableGuid, >> >> + OUT UINT32 *Attributes, >> >> + IN OUT UINTN *DataSize, >> >> + OUT VOID *Data OPTIONAL >> >> + ); >> >> + >> >> +/** >> >> + Return the next variable name and GUID. >> >> + >> >> + This function is called multiple times to retrieve the VariableName >> >> + and VariableGuid of all variables currently available in the system. >> >> + On each call, the previous results are passed into the interface, >> >> + and, on return, the interface returns the data for the next >> >> + interface. When the entire variable list has been returned, >> >> + EFI_NOT_FOUND is returned. >> >> + >> >> + @param This A pointer to this instance of the >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. >> >> + >> >> + @param VariableNameSize On entry, points to the size of the buffer >> pointed to by VariableName. >> >> + On return, the size of the variable name >> buffer. >> >> + @param VariableName On entry, a pointer to a null-terminated >> string that is the variable's name. >> >> + On return, points to the next variable's >> null-terminated name string. >> >> + >> >> + @param VariableGuid On entry, a pointer to an EFI_GUID that is >> the variable's GUID. >> >> + On return, a pointer to the next variable's >> GUID. >> >> + >> >> + @retval EFI_SUCCESS The variable was read successfully. >> >> + @retval EFI_NOT_FOUND The variable could not be found. >> >> + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small >> for the resulting >> >> + data. VariableNameSize is updated >> with the size >> >> + required for the specified variable. >> >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or >> >> + VariableNameSize is NULL. >> >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved >> because of a device error. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +PeiMmGetNextVariableName ( >> >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, >> >> + IN OUT UINTN *VariableNameSize, >> >> + IN OUT CHAR16 *VariableName, >> >> + IN OUT EFI_GUID *VariableGuid >> >> + ); >> >> + >> >> +#endif /* PEI_MM_VARIABLE_LIB_H_ */ >> >> diff --git >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf >> new file mode 100644 >> index 000000000000..d122703e9b5d >> --- /dev/null >> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf >> @@ -0,0 +1,43 @@ >> +## @file -- MmVariablePei.inf >> >> +# Provides interface for reading Secure System Variables during PEI. >> >> +# >> >> +# Copyright (c) Microsoft Corporation. >> >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> >> +## >> >> + >> >> + >> >> +[Defines] >> >> + INF_VERSION = 0x00010005 >> >> + BASE_NAME = MmVariablePei >> >> + FILE_GUID = >> CD660A87-454B-4346-A35C-3D89BF8ECFAF >> >> + MODULE_TYPE = PEIM >> >> + VERSION_STRING = 1.0 >> >> + ENTRY_POINT = PeiMmVariableInitialize >> >> + >> >> +[Sources] >> >> + MmVariablePei.c >> >> + MmVariablePei.h >> >> + >> >> +[Packages] >> >> + MdePkg/MdePkg.dec >> >> + MdeModulePkg/MdeModulePkg.dec >> >> + >> >> +[LibraryClasses] >> >> + PcdLib >> >> + PeiServicesLib >> >> + PeimEntryPoint >> >> + MemoryAllocationLib >> >> + HobLib >> >> + >> >> +[Pcd] >> >> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize >> >> + >> >> +[Protocols] >> >> + gEfiSmmVariableProtocolGuid ## CONSUMES >> >> + >> >> +[Ppis] >> >> + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES >> >> + gEfiPeiMmCommunicationPpiGuid ## CONSUMES >> >> + >> >> +[Depex] >> >> + gEfiPeiMmCommunicationPpiGuid >> >> -- >> 2.40.1.windows.1 >> >> >> >> -=-=-=-=-=-= >> Groups.io Links: You receive all messages sent to this group. >> View/Reply Online (#105956): >> https://edk2.groups.io/g/devel/message/105956 >> Mute This Topic: https://groups.io/mt/99415826/4905953 >> Group Owner: devel+owner@edk2.groups.io >> Unsubscribe: https://edk2.groups.io/g/devel/unsub >> [gaoliming@byosoft.com.cn] >> -=-=-=-=-=-= >> > > > > > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* 回复: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI 2023-06-26 20:10 ` Kun Qin @ 2023-06-27 0:53 ` gaoliming 0 siblings, 0 replies; 8+ messages in thread From: gaoliming @ 2023-06-27 0:53 UTC (permalink / raw) To: devel, kuqin12 Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen', 'Shriram Masanamuthu Chinnathurai', 'Preshit Harlikar' Kun: Thanks for your update. I have no other comments for this patch. Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn> Thanks Liming > -----邮件原件----- > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin > 发送时间: 2023年6月27日 4:11 > 收件人: devel@edk2.groups.io; gaoliming@byosoft.com.cn > 抄送: 'Hao A Wu' <hao.a.wu@intel.com>; 'Jian J Wang' > <jian.j.wang@intel.com>; 'Ronny Hansen' <hansen.ronny@microsoft.com>; > 'Shriram Masanamuthu Chinnathurai' <shriramma@microsoft.com>; 'Preshit > Harlikar' <pharlikar@microsoft.com> > 主题: Re: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: > Introduce MM based variable read service in PEI > > Hi Liming, > > Thanks for catching that. I have removed the PCD usage and resend the > patch here: > https://edk2.groups.io/g/devel/message/106372 > > Could you please let me know if you have any other feedback? > > Per your functionality question, yes, the functionality was verified on > both virtual > and physical ARM platforms. I also added this statement to the v2 cover > letter. > > Thanks, > Kun > > On 6/24/2023 7:23 PM, gaoliming via groups.io wrote: > > Kun: > > Seemly, PcdMaxVariableSize is not used by this module. It can be > removed. > > > > And, has its functionality been verified in the real platform? > > > > Thanks > > Liming > >> -----邮件原件----- > >> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin > >> 发送时间: 2023年6月9日 4:45 > >> 收件人: devel@edk2.groups.io > >> 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao > >> <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>; > Ronny > >> Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu > >> Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar > >> <pharlikar@microsoft.com> > >> 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce > MM > >> based variable read service in PEI > >> > >> From: Kun Qin <kuqin@microsoft.com> > >> > >> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464 > >> > >> This change introduced the Standalone MM based variable read capability > >> in PEI phase for applicable platforms (such as ARM platforms). > >> > >> Similar to the x86 counterpart, MM communicate PPI is used to request > >> variable information from Standalone MM environment. > >> > >> Cc: Hao A Wu <hao.a.wu@intel.com> > >> Cc: Liming Gao <gaoliming@byosoft.com.cn> > >> Cc: Jian J Wang <jian.j.wang@intel.com> > >> > >> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com> > >> Co-authored-by: Shriram Masanamuthu Chinnathurai > >> <shriramma@microsoft.com> > >> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com> > >> Signed-off-by: Kun Qin <kuqin@microsoft.com> > >> --- > >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > | > >> 381 ++++++++++++++++++++ > >> MdeModulePkg/MdeModulePkg.dsc > >> | 1 + > >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > | > >> 134 +++++++ > >> MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > | > >> 43 +++ > >> 4 files changed, 559 insertions(+) > >> > >> diff --git > >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > >> new file mode 100644 > >> index 000000000000..4f937e22e89e > >> --- /dev/null > >> +++ > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c > >> @@ -0,0 +1,381 @@ > >> +/** @file -- MmVariablePei.c > >> > >> + Provides interface for reading Secure System Variables during PEI. > >> > >> + > >> > >> + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> > >> > >> + Copyright (c) Microsoft Corporation.<BR> > >> > >> + SPDX-License-Identifier: BSD-2-Clause-Patent > >> > >> +**/ > >> > >> + > >> > >> +#include "MmVariablePei.h" > >> > >> + > >> > >> +#define MM_VARIABLE_COMM_BUFFER_OFFSET > >> (SMM_COMMUNICATE_HEADER_SIZE + > >> SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) > >> > >> + > >> > >> +// > >> > >> +// Module globals > >> > >> +// > >> > >> +EFI_PEI_READ_ONLY_VARIABLE2_PPI mPeiSecureVariableRead = { > >> > >> + PeiMmGetVariable, > >> > >> + PeiMmGetNextVariableName > >> > >> +}; > >> > >> + > >> > >> +EFI_PEI_PPI_DESCRIPTOR mPeiMmVariablePpi = { > >> > >> + (EFI_PEI_PPI_DESCRIPTOR_PPI | > >> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > >> > >> + &gEfiPeiReadOnlyVariable2PpiGuid, > >> > >> + &mPeiSecureVariableRead > >> > >> +}; > >> > >> + > >> > >> +/** > >> > >> + Entry point of PEI Secure Variable read driver > >> > >> + > >> > >> + @param FileHandle Handle of the file being invoked. > >> > >> + Type EFI_PEI_FILE_HANDLE is defined in > >> FfsFindNextFile(). > >> > >> + @param PeiServices General purpose services available to every > >> PEIM. > >> > >> + > >> > >> + @retval EFI_SUCCESS If the interface could be successfully installed > >> > >> + @retval Others Returned from PeiServicesInstallPpi() > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmVariableInitialize ( > >> > >> + IN EFI_PEI_FILE_HANDLE FileHandle, > >> > >> + IN CONST EFI_PEI_SERVICES **PeiServices > >> > >> + ) > >> > >> +{ > >> > >> + return PeiServicesInstallPpi (&mPeiMmVariablePpi); > >> > >> +} > >> > >> + > >> > >> +/** > >> > >> + Helper function to populate MM communicate header and variable > >> communicate header > >> > >> + and then communicate to PEI. > >> > >> + > >> > >> + @param[in, out] CommunicateBuffer Size of the variable > name. > >> > >> + @param[in] CommunicateBufferSize The entire buffer size to > be > >> sent to MM. > >> > >> + @param[in] Function The MM variable > function > >> value. > >> > >> + > >> > >> + @retval EFI_INVALID_PARAMETER Invalid parameter. > >> > >> + @retval EFI_SUCCESS Find the specified variable. > >> > >> + @retval Others Errors returned by MM > >> communicate or variable service. > >> > >> + > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +PopulateHeaderAndCommunicate ( > >> > >> + IN OUT UINT8 *CommunicateBuffer, > >> > >> + IN UINTN CommunicateBufferSize, > >> > >> + IN UINTN Function > >> > >> + ) > >> > >> +{ > >> > >> + EFI_STATUS Status; > >> > >> + EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi; > >> > >> + EFI_MM_COMMUNICATE_HEADER > *MmCommunicateHeader; > >> > >> + SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader; > >> > >> + > >> > >> + // Minimal sanity check > >> > >> + if ((CommunicateBuffer == NULL) || > >> > >> + (CommunicateBufferSize < > >> MM_VARIABLE_COMM_BUFFER_OFFSET)) > >> > >> + { > >> > >> + Status = EFI_INVALID_PARAMETER; > >> > >> + DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and > >> 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize)); > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + if ((Function != > >> SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) && > >> > >> + (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE)) > >> > >> + { > >> > >> + Status = EFI_INVALID_PARAMETER; > >> > >> + DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", > >> __func__, Function)); > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, > >> NULL, (VOID **)&MmCommunicationPpi); > >> > >> + if (EFI_ERROR (Status)) { > >> > >> + DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM > Communication > >> PPI: %r\n", __func__, Status)); > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + // Zero the entire Communication Buffer Header > >> > >> + MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER > >> *)CommunicateBuffer; > >> > >> + > >> > >> + ZeroMem (MmCommunicateHeader, > >> SMM_COMMUNICATE_HEADER_SIZE); > >> > >> + > >> > >> + // Use gEfiSmmVariableProtocolGuid to request the MM variable > service > >> in Standalone MM > >> > >> + CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, > >> &gEfiSmmVariableProtocolGuid, sizeof (GUID)); > >> > >> + > >> > >> + // Program the MM header size > >> > >> + MmCommunicateHeader->MessageLength = CommunicateBufferSize - > >> SMM_COMMUNICATE_HEADER_SIZE; > >> > >> + > >> > >> + MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER > >> *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE); > >> > >> + > >> > >> + // We are only supporting GetVariable and GetNextVariableName > >> > >> + MmVarCommsHeader->Function = Function; > >> > >> + > >> > >> + // Send the MM request using MmCommunicationPei > >> > >> + Status = MmCommunicationPpi->Communicate > (MmCommunicationPpi, > >> CommunicateBuffer, &CommunicateBufferSize); > >> > >> + if (EFI_ERROR (Status)) { > >> > >> + // Received an error from MM interface. > >> > >> + DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", > __func__, > >> Status)); > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + // MM request was successfully handled by the framework. > >> > >> + // Set status to the Variable Service Status Code > >> > >> + Status = MmVarCommsHeader->ReturnStatus; > >> > >> + if (EFI_ERROR (Status)) { > >> > >> + // We received an error from Variable Service. > >> > >> + // We cant do anymore so return Status > >> > >> + if (Status != EFI_BUFFER_TOO_SMALL) { > >> > >> + DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", > >> __func__, Status)); > >> > >> + } > >> > >> + > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> +Exit: > >> > >> + return Status; > >> > >> +} > >> > >> + > >> > >> +/** > >> > >> + This service retrieves a variable's value using its name and GUID. > >> > >> + > >> > >> + This function is using the Secure Variable Store. If the Data > >> > >> + buffer is too small to hold the contents of the variable, the error > >> > >> + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the > required > >> buffer > >> > >> + size to obtain the data. > >> > >> + > >> > >> + @param This A pointer to this instance of the > >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. > >> > >> + @param VariableName A pointer to a null-terminated > string > >> that is the variable's name. > >> > >> + @param VariableGuid A pointer to an EFI_GUID that is > the > >> variable's GUID. The combination of > >> > >> + VariableGuid and VariableName > >> must be unique. > >> > >> + @param Attributes If non-NULL, on return, points to > the > >> variable's attributes. > >> > >> + @param DataSize On entry, points to the size in > bytes > >> of the Data buffer. > >> > >> + On return, points to the size of > the > >> data returned in Data. > >> > >> + @param Data Points to the buffer which will > hold > >> the returned variable value. > >> > >> + May be NULL with a zero > DataSize in > >> order to determine the size of the buffer needed. > >> > >> + > >> > >> + @retval EFI_SUCCESS The variable was read successfully. > >> > >> + @retval EFI_NOT_FOUND The variable was not found. > >> > >> + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the > >> resulting data. > >> > >> + DataSize is updated with the size > >> required for > >> > >> + the specified variable. > >> > >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, > DataSize > >> or Data is NULL. > >> > >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved > >> because of a device error. > >> > >> + > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmGetVariable ( > >> > >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > >> > >> + IN CONST CHAR16 *VariableName, > >> > >> + IN CONST EFI_GUID *VariableGuid, > >> > >> + OUT UINT32 *Attributes, OPTIONAL > >> > >> + IN OUT UINTN *DataSize, > >> > >> + OUT VOID *Data > OPTIONAL > >> > >> + ) > >> > >> +{ > >> > >> + EFI_STATUS Status; > >> > >> + UINTN MessageSize; > >> > >> + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > >> *MmVarAccessHeader; > >> > >> + UINT8 > >> *MmCommunicateBuffer; > >> > >> + UINTN RequiredPages; > >> > >> + > >> > >> + // Check input parameters > >> > >> + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == > >> NULL)) { > >> > >> + return EFI_INVALID_PARAMETER; > >> > >> + } > >> > >> + > >> > >> + if (VariableName[0] == 0) { > >> > >> + return EFI_NOT_FOUND; > >> > >> + } > >> > >> + > >> > >> + if ((*DataSize > 0) && (Data == NULL)) { > >> > >> + return EFI_INVALID_PARAMETER; > >> > >> + } > >> > >> + > >> > >> + // Allocate required pages to send MM request > >> > >> + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + > >> > >> + OFFSET_OF > >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + > >> > >> + StrSize (VariableName) + *DataSize; > >> > >> + > >> > >> + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); > >> > >> + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); > >> > >> + > >> > >> + if (MmCommunicateBuffer == NULL) { > >> > >> + Status = EFI_OUT_OF_RESOURCES; > >> > >> + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", > >> __func__, Status)); > >> > >> + return Status; > >> > >> + } > >> > >> + > >> > >> + // Zero the entire Communication Buffer > >> > >> + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); > >> > >> + > >> > >> + // > >> > >> + // Program all payload structure contents > >> > >> + // > >> > >> + MmVarAccessHeader = > >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); > >> > >> + > >> > >> + // Variable GUID > >> > >> + CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof > >> (GUID)); > >> > >> + > >> > >> + // Program the max amount of data we accept. > >> > >> + MmVarAccessHeader->DataSize = *DataSize; > >> > >> + > >> > >> + // Get size of the variable name > >> > >> + MmVarAccessHeader->NameSize = StrSize (VariableName); > >> > >> + > >> > >> + // Populate incoming variable name > >> > >> + CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, > >> MmVarAccessHeader->NameSize); > >> > >> + > >> > >> + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, > >> MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); > >> > >> + if (EFI_ERROR (Status)) { > >> > >> + // We received an error from either communicate or Variable > Service. > >> > >> + if (Status != EFI_BUFFER_TOO_SMALL) { > >> > >> + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable > >> service errored: %r\n", __func__, Status)); > >> > >> + } > >> > >> + > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + Status = EFI_SUCCESS; > >> > >> + > >> > >> + // User provided buffer is too small > >> > >> + if (*DataSize < MmVarAccessHeader->DataSize) { > >> > >> + Status = EFI_BUFFER_TOO_SMALL; > >> > >> + } > >> > >> + > >> > >> +Exit: > >> > >> + // Check if we need to set Attributes > >> > >> + if (Attributes != NULL) { > >> > >> + *Attributes = MmVarAccessHeader->Attributes; > >> > >> + } > >> > >> + > >> > >> + *DataSize = MmVarAccessHeader->DataSize; > >> > >> + > >> > >> + if (Status == EFI_SUCCESS) { > >> > >> + CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + > >> MmVarAccessHeader->NameSize, *DataSize); > >> > >> + } > >> > >> + > >> > >> + // Free the Communication Buffer > >> > >> + if (MmCommunicateBuffer != NULL) { > >> > >> + FreePages (MmCommunicateBuffer, RequiredPages); > >> > >> + } > >> > >> + > >> > >> + return Status; > >> > >> +} > >> > >> + > >> > >> +/** > >> > >> + Return the next variable name and GUID. > >> > >> + > >> > >> + This function is called multiple times to retrieve the VariableName > >> > >> + and VariableGuid of all variables currently available in the system. > >> > >> + On each call, the previous results are passed into the interface, > >> > >> + and, on return, the interface returns the data for the next > >> > >> + interface. When the entire variable list has been returned, > >> > >> + EFI_NOT_FOUND is returned. > >> > >> + > >> > >> + @param This A pointer to this instance of the > >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. > >> > >> + > >> > >> + @param VariableNameSize On entry, points to the size of the > buffer > >> pointed to by VariableName. > >> > >> + On return, the size of the variable > name > >> buffer. > >> > >> + @param VariableName On entry, a pointer to a > null-terminated > >> string that is the variable's name. > >> > >> + On return, points to the next variable's > >> null-terminated name string. > >> > >> + > >> > >> + @param VariableGuid On entry, a pointer to an EFI_GUID that > is > >> the variable's GUID. > >> > >> + On return, a pointer to the next > variable's > >> GUID. > >> > >> + > >> > >> + @retval EFI_SUCCESS The variable was read successfully. > >> > >> + @retval EFI_NOT_FOUND The variable could not be found. > >> > >> + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too > small > >> for the resulting > >> > >> + data. VariableNameSize is > updated > >> with the size > >> > >> + required for the specified > variable. > >> > >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > >> > >> + VariableNameSize is NULL. > >> > >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved > >> because of a device error. > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmGetNextVariableName ( > >> > >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > >> > >> + IN OUT UINTN > *VariableNameSize, > >> > >> + IN OUT CHAR16 *VariableName, > >> > >> + IN OUT EFI_GUID *VariableGuid > >> > >> + ) > >> > >> +{ > >> > >> + EFI_STATUS Status; > >> > >> + UINTN > >> MessageSize; > >> > >> + UINT8 > >> *MmCommunicateBuffer; > >> > >> + SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > >> *MmVarGetNextVarHeader; > >> > >> + UINTN > >> RequiredPages; > >> > >> + > >> > >> + // Check input parameters > >> > >> + if ((VariableName == NULL) || > >> > >> + (VariableGuid == NULL) || > >> > >> + (VariableNameSize == NULL) || > >> > >> + (*VariableNameSize == 0)) > >> > >> + { > >> > >> + return EFI_INVALID_PARAMETER; > >> > >> + } > >> > >> + > >> > >> + // Allocate required pages to send MM request > >> > >> + MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET + > >> > >> + OFFSET_OF > >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + > >> > >> + StrSize (VariableName) + *VariableNameSize; > >> > >> + > >> > >> + RequiredPages = EFI_SIZE_TO_PAGES (MessageSize); > >> > >> + MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages); > >> > >> + > >> > >> + if (MmCommunicateBuffer == NULL) { > >> > >> + Status = EFI_OUT_OF_RESOURCES; > >> > >> + DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", > >> __func__, Status)); > >> > >> + return Status; > >> > >> + } > >> > >> + > >> > >> + // Zero the entire Communication Buffer > >> > >> + ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE)); > >> > >> + > >> > >> + // > >> > >> + // Program all payload structure contents > >> > >> + // > >> > >> + MmVarGetNextVarHeader = > >> (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET); > >> > >> + > >> > >> + // Variable GUID > >> > >> + CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, > >> sizeof (GUID)); > >> > >> + > >> > >> + // Program the maximal length of name we can accept. > >> > >> + MmVarGetNextVarHeader->NameSize = *VariableNameSize; > >> > >> + > >> > >> + // Populate incoming variable name > >> > >> + CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, > VariableName, > >> MmVarGetNextVarHeader->NameSize); > >> > >> + > >> > >> + // Send the MM request using MmCommunicationPei > >> > >> + Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, > >> MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME); > >> > >> + if (EFI_ERROR (Status)) { > >> > >> + // We received an error from either communicate or Variable > Service. > >> > >> + if (Status != EFI_BUFFER_TOO_SMALL) { > >> > >> + DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable > >> service errored: %r\n", __func__, Status)); > >> > >> + } > >> > >> + > >> > >> + goto Exit; > >> > >> + } > >> > >> + > >> > >> + Status = EFI_SUCCESS; > >> > >> + > >> > >> + // User provided buffer is too small > >> > >> + if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) { > >> > >> + Status = EFI_BUFFER_TOO_SMALL; > >> > >> + } > >> > >> + > >> > >> +Exit: > >> > >> + // Update the name size to be returned > >> > >> + *VariableNameSize = MmVarGetNextVarHeader->NameSize; > >> > >> + > >> > >> + if (Status == EFI_SUCCESS) { > >> > >> + CopyMem ((VOID *)VariableName, (UINT8 > >> *)MmVarGetNextVarHeader->Name, *VariableNameSize); > >> > >> + CopyMem ((VOID *)VariableGuid, (UINT8 > >> *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID)); > >> > >> + } > >> > >> + > >> > >> + // Free the Communication Buffer > >> > >> + if (MmCommunicateBuffer != NULL) { > >> > >> + FreePages (MmCommunicateBuffer, RequiredPages); > >> > >> + } > >> > >> + > >> > >> + return Status; > >> > >> +} > >> > >> diff --git a/MdeModulePkg/MdeModulePkg.dsc > >> b/MdeModulePkg/MdeModulePkg.dsc > >> index 5b1f50e9c084..1aedfe280ae1 100644 > >> --- a/MdeModulePkg/MdeModulePkg.dsc > >> +++ b/MdeModulePkg/MdeModulePkg.dsc > >> @@ -400,6 +400,7 @@ [Components] > >> MdeModulePkg/Application/VariableInfo/VariableInfo.inf > >> > >> > >> > MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf > >> > >> MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > >> > >> + MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > >> > >> MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf > >> > >> MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf > >> > >> > >> > MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > >> > >> diff --git > >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > >> new file mode 100644 > >> index 000000000000..0feed8cd1cb6 > >> --- /dev/null > >> +++ > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h > >> @@ -0,0 +1,134 @@ > >> +/** @file -- MmVariablePei.h > >> > >> + Provides interface for reading Secure System Variables during PEI. > >> > >> + > >> > >> + Copyright (c) Microsoft Corporation. > >> > >> + SPDX-License-Identifier: BSD-2-Clause-Patent > >> > >> +**/ > >> > >> + > >> > >> +#ifndef PEI_MM_VARIABLE_LIB_H_ > >> > >> +#define PEI_MM_VARIABLE_LIB_H_ > >> > >> + > >> > >> +#include <PiPei.h> > >> > >> +#include <Uefi/UefiSpec.h> > >> > >> + > >> > >> +#include <Library/DebugLib.h> > >> > >> +#include <Library/PcdLib.h> > >> > >> +#include <Library/BaseMemoryLib.h> > >> > >> +#include <Library/PeimEntryPoint.h> > >> > >> +#include <Library/PeiServicesLib.h> > >> > >> +#include <Library/MemoryAllocationLib.h> > >> > >> +#include <Library/HobLib.h> > >> > >> + > >> > >> +#include <Guid/SmmVariableCommon.h> > >> > >> + > >> > >> +#include <Ppi/ReadOnlyVariable2.h> > >> > >> +#include <Ppi/MmCommunication.h> > >> > >> + > >> > >> +#include <Protocol/SmmVariable.h> > >> > >> +#include <Protocol/MmCommunication.h> > >> > >> + > >> > >> +/** > >> > >> + Entry point of PEI Secure Variable read driver > >> > >> + > >> > >> + @param FileHandle Handle of the file being invoked. > >> > >> + Type EFI_PEI_FILE_HANDLE is defined in > >> FfsFindNextFile(). > >> > >> + @param PeiServices General purpose services available to every > >> PEIM. > >> > >> + > >> > >> + @retval EFI_SUCCESS If the interface could be successfully installed > >> > >> + @retval Others Returned from PeiServicesInstallPpi() > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmVariableInitialize ( > >> > >> + IN EFI_PEI_FILE_HANDLE FileHandle, > >> > >> + IN CONST EFI_PEI_SERVICES **PeiServices > >> > >> + ); > >> > >> + > >> > >> +/** > >> > >> + > >> > >> + This function enables the read of Secure Variables during PEI. > >> > >> + > >> > >> + This function is using the Secure Variable Store.If the Data > >> > >> + buffer is too small to hold the contents of the variable, the error > >> > >> + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the > required > >> buffer > >> > >> + size to obtain the data. > >> > >> + > >> > >> + The function performs the following: > >> > >> + > >> > >> + 1) Creates an MM request > >> > >> + 2) Fills out the following data structures for the Secure Variable > > Service > >> + > >> > SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT > >> E_ACCESS_VARIABLE > >> > >> + 3) Adds the MM data structures to the MM request. > >> > >> + 4) Sends the MM request to EL3 using MmCommunicationPeiLib. > >> > >> + 5) The MM request is sent to S-EL0. > >> > >> + 6) The MM request is then handled by the registered handler with > GUID: > >> gEfiSmmVariableProtocolGuid > >> > >> + > >> > >> + @param This A pointer to this instance of the > >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. > >> > >> + @param VariableName A pointer to a null-terminated > string > >> that is the variable's name. > >> > >> + @param VariableGuid A pointer to an EFI_GUID that is > the > >> variable's GUID. The combination of > >> > >> + VariableGuid and VariableName > >> must be unique. > >> > >> + @param Attributes If non-NULL, on return, points to > the > >> variable's attributes. > >> > >> + @param DataSize On entry, points to the size in > bytes > >> of the Data buffer. > >> > >> + On return, points to the size of > the > >> data returned in Data. > >> > >> + @param Data Points to the buffer which will > hold > >> the returned variable value. > >> > >> + May be NULL with a zero > DataSize in > >> order to determine the size of the buffer needed. > >> > >> + > >> > >> + @retval EFI_SUCCESS The variable was read successfully. > >> > >> + @retval EFI_NOT_FOUND The variable was not found. > >> > >> + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the > >> resulting data. > >> > >> + DataSize is updated with the size > >> required for > >> > >> + the specified variable. > >> > >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, > DataSize > >> or Data is NULL. > >> > >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved > >> because of a device error. > >> > >> + > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmGetVariable ( > >> > >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > >> > >> + IN CONST CHAR16 *VariableName, > >> > >> + IN CONST EFI_GUID *VariableGuid, > >> > >> + OUT UINT32 *Attributes, > >> > >> + IN OUT UINTN *DataSize, > >> > >> + OUT VOID *Data > OPTIONAL > >> > >> + ); > >> > >> + > >> > >> +/** > >> > >> + Return the next variable name and GUID. > >> > >> + > >> > >> + This function is called multiple times to retrieve the VariableName > >> > >> + and VariableGuid of all variables currently available in the system. > >> > >> + On each call, the previous results are passed into the interface, > >> > >> + and, on return, the interface returns the data for the next > >> > >> + interface. When the entire variable list has been returned, > >> > >> + EFI_NOT_FOUND is returned. > >> > >> + > >> > >> + @param This A pointer to this instance of the > >> EFI_PEI_READ_ONLY_VARIABLE2_PPI. > >> > >> + > >> > >> + @param VariableNameSize On entry, points to the size of the > buffer > >> pointed to by VariableName. > >> > >> + On return, the size of the variable > name > >> buffer. > >> > >> + @param VariableName On entry, a pointer to a > null-terminated > >> string that is the variable's name. > >> > >> + On return, points to the next variable's > >> null-terminated name string. > >> > >> + > >> > >> + @param VariableGuid On entry, a pointer to an EFI_GUID that > is > >> the variable's GUID. > >> > >> + On return, a pointer to the next > variable's > >> GUID. > >> > >> + > >> > >> + @retval EFI_SUCCESS The variable was read successfully. > >> > >> + @retval EFI_NOT_FOUND The variable could not be found. > >> > >> + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too > small > >> for the resulting > >> > >> + data. VariableNameSize is > updated > >> with the size > >> > >> + required for the specified > variable. > >> > >> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > >> > >> + VariableNameSize is NULL. > >> > >> + @retval EFI_DEVICE_ERROR The variable could not be retrieved > >> because of a device error. > >> > >> +**/ > >> > >> +EFI_STATUS > >> > >> +EFIAPI > >> > >> +PeiMmGetNextVariableName ( > >> > >> + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > >> > >> + IN OUT UINTN > *VariableNameSize, > >> > >> + IN OUT CHAR16 *VariableName, > >> > >> + IN OUT EFI_GUID *VariableGuid > >> > >> + ); > >> > >> + > >> > >> +#endif /* PEI_MM_VARIABLE_LIB_H_ */ > >> > >> diff --git > >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > >> new file mode 100644 > >> index 000000000000..d122703e9b5d > >> --- /dev/null > >> +++ > b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf > >> @@ -0,0 +1,43 @@ > >> +## @file -- MmVariablePei.inf > >> > >> +# Provides interface for reading Secure System Variables during PEI. > >> > >> +# > >> > >> +# Copyright (c) Microsoft Corporation. > >> > >> +# SPDX-License-Identifier: BSD-2-Clause-Patent > >> > >> +## > >> > >> + > >> > >> + > >> > >> +[Defines] > >> > >> + INF_VERSION = 0x00010005 > >> > >> + BASE_NAME = MmVariablePei > >> > >> + FILE_GUID = > >> CD660A87-454B-4346-A35C-3D89BF8ECFAF > >> > >> + MODULE_TYPE = PEIM > >> > >> + VERSION_STRING = 1.0 > >> > >> + ENTRY_POINT = PeiMmVariableInitialize > >> > >> + > >> > >> +[Sources] > >> > >> + MmVariablePei.c > >> > >> + MmVariablePei.h > >> > >> + > >> > >> +[Packages] > >> > >> + MdePkg/MdePkg.dec > >> > >> + MdeModulePkg/MdeModulePkg.dec > >> > >> + > >> > >> +[LibraryClasses] > >> > >> + PcdLib > >> > >> + PeiServicesLib > >> > >> + PeimEntryPoint > >> > >> + MemoryAllocationLib > >> > >> + HobLib > >> > >> + > >> > >> +[Pcd] > >> > >> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize > >> > >> + > >> > >> +[Protocols] > >> > >> + gEfiSmmVariableProtocolGuid ## CONSUMES > >> > >> + > >> > >> +[Ppis] > >> > >> + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES > >> > >> + gEfiPeiMmCommunicationPpiGuid ## CONSUMES > >> > >> + > >> > >> +[Depex] > >> > >> + gEfiPeiMmCommunicationPpiGuid > >> > >> -- > >> 2.40.1.windows.1 > >> > >> > >> > >> -=-=-=-=-=-= > >> Groups.io Links: You receive all messages sent to this group. > >> View/Reply Online (#105956): > >> https://edk2.groups.io/g/devel/message/105956 > >> Mute This Topic: https://groups.io/mt/99415826/4905953 > >> Group Owner: devel+owner@edk2.groups.io > >> Unsubscribe: https://edk2.groups.io/g/devel/unsub > >> [gaoliming@byosoft.com.cn] > >> -=-=-=-=-=-= > >> > > > > > > > > > > > > > > > > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-06-27 0:53 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin 2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin 2023-06-22 19:17 ` Sami Mujawar 2023-06-26 20:07 ` Kun Qin 2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin 2023-06-25 2:23 ` 回复: [edk2-devel] " gaoliming 2023-06-26 20:10 ` Kun Qin 2023-06-27 0:53 ` 回复: " gaoliming
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox