From 8d7bae0adadfc90f2ce6077bdeb58833354e4fe7 Mon Sep 17 00:00:00 2001 From: Oliver Smith-Denny Date: Sun, 21 Apr 2024 06:33:55 -0700 Subject: [PATCH] Add Adv Logger PRM Module This commit adds the Adv Logger PRM Module. It is an alternate way to fetch the Adv Logger Log that does not require SMM/Secure World access. It also is independently serviceable from the OS. - [x] Impacts functionality? - **Functionality** - Does the change ultimately impact how firmware functions? - Examples: Add a new library, publish a new PPI, update an algorithm, ... - [x] Impacts security? - **Security** - Does the change have a direct security impact on an application, flow, or firmware? - Examples: Crypto algorithm change, buffer overflow fix, parameter validation improvement, ... - [ ] Breaking change? - **Breaking change** - Will anyone consuming this change experience a break in build or boot behavior? - Examples: Add a new library class, move a module to a different repo, call a function in a new library class in a pre-existing module, ... - [x] Includes tests? - **Tests** - Does the change include any explicit test code? - Examples: Unit tests, integration tests, robot tests, ... - [x] Includes documentation? - **Documentation** - Does the change contain explicit documentation additions outside direct code modifications (and comments)? - Examples: Update readme file, add feature readme file, link to documentation on an a separate Web page, ... Tested on various physical and virtual platforms to ensure the log was the same between the GetVariable interface and the PRM interface. See the README update for integration instructions. --- .../AdvLoggerOsConnectorPrm.c | 164 +++++ .../AdvLoggerOsConnectorPrm.h | 36 + .../AdvLoggerOsConnectorPrm.inf | 42 ++ .../AdvLoggerOsConnectorPrmGoogleTest.cpp | 216 ++++++ .../AdvLoggerOsConnectorPrmGoogleTest.inf | 31 + .../AdvLoggerOsConnectorPrmConfigLib.c | 298 ++++++++ .../AdvLoggerOsConnectorPrmConfigLib.inf | 47 ++ .../AdvLoggerPrmConfigLibGoogleTest.cpp | 688 ++++++++++++++++++ .../AdvLoggerPrmConfigLibGoogleTest.inf | 44 ++ AdvLoggerPkg/AdvLoggerPkg.ci.yaml | 21 +- AdvLoggerPkg/AdvLoggerPkg.dec | 2 +- AdvLoggerPkg/AdvLoggerPkg.dsc | 2 + .../PrmFuncSample/PrmFunc/prmfuncsample.c | 238 ++++++ .../PrmFuncSample/PrmFunc/prmfuncsample.h | 74 ++ .../PrmFuncSample/PrmFunc/prmfuncsample.inf | 55 ++ .../PrmFunc/prmfuncsample.vcxproj | 170 +++++ .../PrmFunc/prmfuncsample.vcxproj.Filters | 31 + .../Windows/PrmFuncSample/README.md | 41 ++ .../Windows/PrmFuncSample/prmsample.sln | 33 + AdvLoggerPkg/Docs/ReadMe.md | 50 +- AdvLoggerPkg/Test/AdvLoggerHostTest.dsc | 47 ++ 21 files changed, 2324 insertions(+), 6 deletions(-) create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.c create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.h create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.cpp create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.inf create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.c create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.cpp create mode 100644 AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.inf create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.c create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.h create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj.Filters create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/README.md create mode 100644 AdvLoggerPkg/Application/Windows/PrmFuncSample/prmsample.sln create mode 100644 AdvLoggerPkg/Test/AdvLoggerHostTest.dsc diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.c b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.c new file mode 100644 index 0000000000..9a462ae910 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.c @@ -0,0 +1,164 @@ +/** @file AdvLoggerOsConnectorPrm.c + + This driver gives an interface to OS components to fetch the AdvancedLogger memory log. + + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include +#include +#include +#include + +#include "AdvLoggerOsConnectorPrm.h" + +typedef struct { + VOID *OutputBuffer; + UINT32 *OutputBufferSize; +} ADVANCED_LOGGER_PRM_PARAMETER_BUFFER; + +/** + CheckAddress + + The address of the ADVANCE_LOGGER_INFO block pointer is captured before END_OF_DXE. + LogBufferOffset, LogCurrentOffset, and LogBufferSize, could be written to by untrusted code. Here, we check that + the offsets are within the allocated mLoggerInfo space, and that LogBufferSize, which is used in multiple places + to see if a new message will fit into the log buffer, is valid. + + @param DataBuf PRM static data buffer containing LoggerInfo pointer + + @return BOOLEAN TRUE - LoggerInfo passes security checks + @return BOOLEAN FALSE- LoggerInfo failed security checks + +**/ +STATIC +BOOLEAN +ValidateInfoBlock ( + IN ADV_LOGGER_PRM_DATA_BUFFER *DataBuf + ) +{ + if ((DataBuf == NULL) || (DataBuf->LoggerInfo == NULL)) { + return FALSE; + } + + if (DataBuf->LoggerInfo->Signature != ADVANCED_LOGGER_SIGNATURE) { + return FALSE; + } + + // most ValidateInfoBlocks check if LogBufferOffset == sizeof (*LoggerInfo) + // we can't do that in the PRM because it is independently serviceable at OS runtime + // we may be paired with a FW that has a different logger info structure size, so + // we have to go based on what the boot time FW tells us + + if ((DataBuf->LoggerInfo->LogCurrentOffset > TOTAL_LOG_SIZE_WITH_ALI (DataBuf->LoggerInfo)) || + (DataBuf->LoggerInfo->LogCurrentOffset < DataBuf->LoggerInfo->LogBufferOffset)) + { + return FALSE; + } + + // ensure that the passed in sizes match what we see in the advanced logger structure + if ((DataBuf->ExpectedLogSize != DataBuf->LoggerInfo->LogBufferSize) || + (DataBuf->ExpectedHeaderSize != DataBuf->LoggerInfo->LogBufferOffset)) + { + return FALSE; + } + + return TRUE; +} + +/** + The Advanced Logger Os Connector PRM handler. + + This handler reads the AdvancedLogger buffer and copies the data to the caller supplied buffer. + + @param[in] ParameterBuffer A pointer to the PRM handler parameter buffer + @param[in] ContextBuffer A pointer to the PRM handler context buffer + + @retval EFI_STATUS The PRM handler executed successfully. + @retval Others An error occurred in the PRM handler. + +**/ +PRM_HANDLER_EXPORT (AdvLoggerOsConnectorPrmHandler) { + ADVANCED_LOGGER_PRM_PARAMETER_BUFFER *ParamBuf; + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf = NULL; + + if ((ParameterBuffer == NULL) || (ContextBuffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (ContextBuffer->StaticDataBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Verify PRM data buffer signature is valid + // + if ( + (ContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE) || + (ContextBuffer->StaticDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE)) + { + return EFI_NOT_FOUND; + } + + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)ContextBuffer->StaticDataBuffer->Data; + + if (!ValidateInfoBlock (DataBuf)) { + return EFI_COMPROMISED_DATA; + } + + ParamBuf = (ADVANCED_LOGGER_PRM_PARAMETER_BUFFER *)ParameterBuffer; + + if (ParamBuf->OutputBufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*(ParamBuf->OutputBufferSize) < DataBuf->ExpectedLogSize + DataBuf->ExpectedHeaderSize) { + *ParamBuf->OutputBufferSize = DataBuf->ExpectedLogSize + DataBuf->ExpectedHeaderSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (ParamBuf->OutputBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The length to copy we take from the static data buffer, populated by the FW from a fixed at build PCD + // We do this so we do not have to trust the writeable LoggerInfo structure. We confirm the header size and + // data size against the structure's values to ensure they match + // + CopyMem (ParamBuf->OutputBuffer, (CONST VOID *)DataBuf->LoggerInfo, DataBuf->ExpectedLogSize + DataBuf->ExpectedHeaderSize); + + return EFI_SUCCESS; +} + +// +// Register the PRM export information for this PRM Module +// +PRM_MODULE_EXPORT ( + PRM_HANDLER_EXPORT_ENTRY (ADVANCED_LOGGER_OS_CONNECTOR_PRM_HANDLER_GUID, AdvLoggerOsConnectorPrmHandler) + ); + +/** + Module entry point. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable A pointer to the system table. + + @retval EFI_SUCCESS This function always returns success. + +**/ +EFI_STATUS +EFIAPI +AdvLoggerOsConnectorPrmEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.h b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.h new file mode 100644 index 0000000000..a816363b40 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.h @@ -0,0 +1,36 @@ +/** @file AdvLoggerOsConnectorPrm.h + + Definitions to share between the AdvLogger PRM and PRM config lib + + Copyright (C) Microsoft Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef ADV_LOGGER_OS_CONNECTOR_PRM_H_ +#define ADV_LOGGER_OS_CONNECTOR_PRM_H_ + +// {B4DFA4A2-EAD0-4F55-998B-EA5BE68F73FD} +STATIC CONST EFI_GUID mPrmModuleGuid = { + 0xb4dfa4a2, 0xead0, 0x4f55, { 0x99, 0x8b, 0xea, 0x5b, 0xe6, 0x8f, 0x73, 0xfd } +}; + +// {0f8aef11-77b8-4d7f-84cc-fe0cce64ac14} +STATIC CONST EFI_GUID mAdvLoggerOsConnectorPrmHandlerGuid = { + 0x0f8aef11, 0x77b8, 0x4d7f, { 0x84, 0xcc, 0xfe, 0x0c, 0xce, 0x64, 0xac, 0x14 } +}; + +// {0f8aef11-77b8-4d7f-84cc-fe0cce64ac14} +#define ADVANCED_LOGGER_OS_CONNECTOR_PRM_HANDLER_GUID {0x0f8aef11, 0x77b8, 0x4d7f, {0x84, 0xcc, 0xfe, 0x0c, 0xce, 0x64, 0xac, 0x14}} + +#pragma pack (push, 1) + +typedef struct { + ADVANCED_LOGGER_INFO *LoggerInfo; + UINT32 ExpectedLogSize; + UINT32 ExpectedHeaderSize; +} ADV_LOGGER_PRM_DATA_BUFFER; + +#pragma pack (pop) + +#endif // ADV_LOGGER_OS_CONNECTOR_PRM_H_ diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf new file mode 100644 index 0000000000..0b242aa873 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf @@ -0,0 +1,42 @@ +## @file +# AdvancedLogger OS Connector PRM Driver +# +# This driver gives an interface to OS components to fetch/clear the AdvancedLogger memory log. +# +# Copyright (c) Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.17 + BASE_NAME = AdvLoggerOsConnectorPrm + FILE_GUID = B4DFA4A2-EAD0-4F55-998B-EA5BE68F73FD + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AdvLoggerOsConnectorPrmEntry + +[Sources] + AdvLoggerOsConnectorPrm.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + PrmPkg/PrmPkg.dec + AdvLoggerPkg/AdvLoggerPkg.dec + +[LibraryClasses] + BaseLib + PrintLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + +[Depex] + TRUE + +[BuildOptions.common] + MSFT:*_*_*_DLINK_FLAGS = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0 + MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader + + GCC:*_*_AARCH64_GENFW_FLAGS = --keepoptionalheader --prm + GCC:*_*_AARCH64_DLINK_FLAGS = -Wl,--no-gc-sections -Wl,--require-defined=PrmModuleExportDescriptor -Wl,--require-defined=CheckStaticDataBufferPrmHandler diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.cpp b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.cpp new file mode 100644 index 0000000000..5981892241 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.cpp @@ -0,0 +1,216 @@ +/** @file + + This unit tests AdvLoggerOsConnectorPrm + + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include + +extern "C" { + #include + #include + #include + #include + #include + #include "../AdvLoggerOsConnectorPrm.h" + + typedef struct { + VOID *OutputBuffer; + UINT32 *OutputBufferSize; + } ADVANCED_LOGGER_PRM_PARAMETER_BUFFER; + + BOOLEAN + ValidateInfoBlock ( + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf + ); + + PRM_HANDLER_EXPORT (AdvLoggerOsConnectorPrmHandler); +} + +// *----------------------------------------------------------------------------------* +// * Test Contexts * +// *----------------------------------------------------------------------------------* + +using namespace testing; + +/// ================================================================================================ +/// ================================================================================================ +/// +/// TEST CASES +/// +/// ================================================================================================ +/// ================================================================================================ + +// +// Declarations for unit tests +// +class AdvLoggerOsConnectorPrmTest : public Test { +protected: +}; + +TEST_F (AdvLoggerOsConnectorPrmTest, ValidateInfoBlockTests) { + ADV_LOGGER_PRM_DATA_BUFFER DataBuf; + BOOLEAN Result; + ADVANCED_LOGGER_INFO LoggerInfo; + + // Test NULL DataBuf + Result = ValidateInfoBlock (NULL); + EXPECT_EQ (Result, FALSE); + + // Test NULL LoggerInfo + DataBuf.LoggerInfo = NULL; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test Bad LoggerInfo Signature + DataBuf.LoggerInfo = &LoggerInfo; + LoggerInfo.Signature = 0xDEADBEEF; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test LogCurrentOffset > Total Log Size + LoggerInfo.Signature = ADVANCED_LOGGER_SIGNATURE; + LoggerInfo.LogBufferOffset = sizeof (LoggerInfo); + LoggerInfo.LogBufferSize = 0x1; + LoggerInfo.LogCurrentOffset = 0x7777; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test LogCurrentOffset < LogBufferOffset + LoggerInfo.LogBufferSize = 0x10000; + LoggerInfo.LogCurrentOffset = 0x3; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test ExpectedLogSize != LogBufferSize + DataBuf.ExpectedLogSize = 0x9999; + LoggerInfo.LogCurrentOffset = 0x150; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test ExpectedHeaderSize != LogBufferOffset + DataBuf.ExpectedHeaderSize = sizeof (LoggerInfo) - 0x10; + DataBuf.ExpectedLogSize = 0x10000; + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test success + DataBuf.ExpectedHeaderSize = sizeof (LoggerInfo); + Result = ValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, TRUE); +} + +TEST_F (AdvLoggerOsConnectorPrmTest, AdvLoggerOsConnectorPrmHandlerTests) { + EFI_STATUS Status; + ADVANCED_LOGGER_PRM_PARAMETER_BUFFER ParamBuf; + PRM_CONTEXT_BUFFER ContextBuf; + CHAR8 OutputBuf[0x100]; + UINT32 OutputBufSize = (UINT32)0x0; + ADV_LOGGER_PRM_DATA_BUFFER *LogDataBuf; + CHAR8 StaticDataBuffer[sizeof (PRM_DATA_BUFFER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER)]; + CHAR8 BigLoggerInfo[0x100]; + + // Test NULL ParameterBuffer + Status = AdvLoggerOsConnectorPrmHandler (NULL, NULL); + EXPECT_EQ (Status, EFI_INVALID_PARAMETER); + + // Test NULL ContextBuffer + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, NULL); + EXPECT_EQ (Status, EFI_INVALID_PARAMETER); + + // Test NULL StaticDataBuffer + ContextBuf.StaticDataBuffer = NULL; + ParamBuf.OutputBuffer = &OutputBuf; + ParamBuf.OutputBufferSize = &OutputBufSize; + memset (OutputBuf, 'O', 0x100); + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_INVALID_PARAMETER); + EXPECT_EQ (OutputBufSize, (UINT32)0); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test Bad Context Buffer Signature + ContextBuf.Signature = 0xDEADBEEF; + ContextBuf.StaticDataBuffer = (PRM_DATA_BUFFER *)StaticDataBuffer; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_NOT_FOUND); + EXPECT_EQ (OutputBufSize, (UINT32)0x0); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test Bad Static Data Buffer Signature + ContextBuf.Signature = PRM_CONTEXT_BUFFER_SIGNATURE; + ContextBuf.StaticDataBuffer->Header.Signature = 0xDEADBEEF; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_NOT_FOUND); + EXPECT_EQ (OutputBufSize, (UINT32)0x0); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test ValidateInfoBlock Fail + ContextBuf.StaticDataBuffer->Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE; + LogDataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)ContextBuf.StaticDataBuffer->Data; + LogDataBuf->LoggerInfo = (ADVANCED_LOGGER_INFO *)BigLoggerInfo; + LogDataBuf->LoggerInfo->Signature = 0xDEADBEEF; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_COMPROMISED_DATA); + EXPECT_EQ (OutputBufSize, (UINT32)0x0); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test OutputBufferSize == NULL + LogDataBuf->LoggerInfo->Signature = ADVANCED_LOGGER_SIGNATURE; + // use a made up header size here, to test we don't have the assumption LogBufferOffset == sizeof (LoggerInfo) + // which may not be true for the PRM as it can be matched with a FW with a different header size + LogDataBuf->LoggerInfo->LogBufferSize = 0x100 - 0x88; + LogDataBuf->LoggerInfo->LogBufferOffset = 0x88; + LogDataBuf->LoggerInfo->LogCurrentOffset = 0x88; + LogDataBuf->ExpectedHeaderSize = 0x88; + LogDataBuf->ExpectedLogSize = LogDataBuf->LoggerInfo->LogBufferSize; + ParamBuf.OutputBufferSize = NULL; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_INVALID_PARAMETER); + EXPECT_EQ (OutputBufSize, (UINT32)0x0); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test too small OutputBufferSize + ParamBuf.OutputBufferSize = &OutputBufSize; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_BUFFER_TOO_SMALL); + EXPECT_EQ (OutputBufSize, (UINT32)0x100); + for (int i = 0; i < 0x100; i++) { + EXPECT_EQ (OutputBuf[i], 'O'); + } + + // Test NULL OutputBuffer + ParamBuf.OutputBuffer = NULL; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_INVALID_PARAMETER); + EXPECT_EQ (OutputBufSize, (UINT32)0x100); + + // Test success + ParamBuf.OutputBuffer = OutputBuf; + Status = AdvLoggerOsConnectorPrmHandler (&ParamBuf, &ContextBuf); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (OutputBufSize, (UINT32)0x100); + EXPECT_THAT (OutputBuf, BufferEq (BigLoggerInfo, (UINT32)0x100)); +} + +int +main ( + int argc, + char *argv[] + ) +{ + testing::InitGoogleTest (&argc, argv); + return RUN_ALL_TESTS (); +} diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.inf b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.inf new file mode 100644 index 0000000000..bf173d7e1d --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.inf @@ -0,0 +1,31 @@ +## @file AdvLoggerOsConnectorPrmGoogleTest.inf +# +# This unit tests the AdvLoggerOsConnectorPrm Module +# +# Copyright (c) Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AdvLoggerOsConnectorPrmGoogleTest + FILE_GUID = 7027B281-BE64-4D83-9667-3CE9B041E2B2 + MODULE_TYPE = HOST_APPLICATION + VERSION_STRING = 1.0 + +[Sources] + AdvLoggerOsConnectorPrmGoogleTest.cpp + ../AdvLoggerOsConnectorPrm.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + AdvLoggerPkg/AdvLoggerPkg.dec + PrmPkg/PrmPkg.dec + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec + +[LibraryClasses] + GoogleTestLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /std:c++latest \ No newline at end of file diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.c b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.c new file mode 100644 index 0000000000..2112354696 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.c @@ -0,0 +1,298 @@ +/** @file + + The boot services environment configuration library for the Adv Logger OS Connector PRM module. + + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../../AdvLoggerOsConnectorPrm.h" + +// we need to have a module global of the static data buffer so that we can update the LoggerInfo pointer +// on the virtual address change event +STATIC PRM_DATA_BUFFER *mStaticDataBuffer = NULL; +STATIC EFI_HANDLE mPrmConfigProtocolHandle = NULL; +EFI_EVENT mVirtualAddressChangeEvent; + +/** + Convert internal pointer addresses to virtual addresses. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, which + is implementation-dependent. +**/ +VOID +EFIAPI +AdvLoggerOsConnectorPrmVirtualAddressCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf; + + if (mStaticDataBuffer != NULL) { + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)mStaticDataBuffer->Data; + Status = EfiConvertPointer (0, (VOID **)&(DataBuf->LoggerInfo)); + if (EFI_ERROR (Status)) { + // if we failed to convert the pointer, we need to nullify the data as the PRM won't know this isn't + // a virtual pointer and could read random kernel memory or crash the kernel if the physical address + // is invalid in virtual space. We don't free the old StaticDataBuffer as we are past ExitBootServices + // at this point + DataBuf->LoggerInfo = NULL; + DataBuf->ExpectedHeaderSize = 0; + DataBuf->ExpectedLogSize = 0; + } + } +} + +/** + CheckAddress + + The address of the ADVANCE_LOGGER_INFO block pointer is captured before END_OF_DXE. + LogBufferOffset, LogCurrentOffset, and LogBufferSize, could be written to by untrusted code. Here, we check that + the offsets are within the allocated mLoggerInfo space, and that LogBufferSize, which is used in multiple places + to see if a new message will fit into the log buffer, is valid. + + @param DataBuf PRM static data buffer containing LoggerInfo pointer + + @return BOOLEAN TRUE - LoggerInfo passes security checks + @return BOOLEAN FALSE- LoggerInfo failed security checks + +**/ +STATIC +BOOLEAN +PrmConfigLibValidateInfoBlock ( + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf + ) +{ + if ((DataBuf == NULL) || (DataBuf->LoggerInfo == NULL)) { + return FALSE; + } + + if (DataBuf->LoggerInfo->Signature != ADVANCED_LOGGER_SIGNATURE) { + return FALSE; + } + + if (DataBuf->LoggerInfo->LogBufferOffset != sizeof (*(DataBuf->LoggerInfo))) { + return FALSE; + } + + if ((DataBuf->LoggerInfo->LogCurrentOffset > TOTAL_LOG_SIZE_WITH_ALI (DataBuf->LoggerInfo)) || + (DataBuf->LoggerInfo->LogCurrentOffset < DataBuf->LoggerInfo->LogBufferOffset)) + { + return FALSE; + } + + // ensure that the passed in sizes match what we see in the advanced logger structure + if ((DataBuf->ExpectedLogSize != DataBuf->LoggerInfo->LogBufferSize) || + (DataBuf->ExpectedHeaderSize != DataBuf->LoggerInfo->LogBufferOffset)) + { + return FALSE; + } + + return TRUE; +} + +/** + Constructor of the PRM configuration library. + + @param[in] ImageHandle The image handle of the driver. + @param[in] SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The shell command handlers were installed successfully. + @retval EFI_UNSUPPORTED The shell level required was not found. +**/ +EFI_STATUS +EFIAPI +AdvLoggerOsConnectorPrmConfigLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + PRM_CONFIG_PROTOCOL *PrmConfigProtocol = NULL; + ADVANCED_LOGGER_PROTOCOL *LoggerProtocol; + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf = NULL; + PRM_CONTEXT_BUFFER *PrmContextBuffer = NULL; + UINTN DataBufferLength; + + // + // Before we do anything, let's make sure the PCD was set correctly for the size. If we have + // a log buffer size < sizeof (AdvancedLoggerInfo), we need to fail as that is a misconfiguration. + // This is the one place in this lib where we want to assert, as this is a dangerous configuration + // that will cause buffer overflow issues + // + if (FixedPcdGet32 (PcdAdvancedLoggerPages) < sizeof (ADVANCED_LOGGER_INFO)) { + DEBUG (( + DEBUG_ERROR, + "%a PcdAdvancedLoggerPages is < sizeof (ADVANCED_LOGGER_INFO)! This is a misconfiguration.", + __func__ + )); + ASSERT (FixedPcdGet32 (PcdAdvancedLoggerPages) >= sizeof (ADVANCED_LOGGER_INFO)); + goto Done; + } + + // + // Length of the data buffer = Buffer Header Size + Size of LoggerInfo pointer + // + DataBufferLength = sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER); + + mStaticDataBuffer = AllocateRuntimeZeroPool (DataBufferLength); + if (mStaticDataBuffer == NULL) { + DEBUG ((DEBUG_ERROR, "%a Failed to allocate static buffer\n", __func__)); + goto Done; + } + + // + // Locate the Logger Information block. + // + Status = gBS->LocateProtocol ( + &gAdvancedLoggerProtocolGuid, + NULL, + (VOID **)&LoggerProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a Failed to find Advanced Logger Protocol\n", __func__)); + goto Done; + } + + // + // To ensure we only read the size of the log buffer in the PRM, read the log buffer size + // directly from the PCD. We need to share the header size we are using, which is recorded as + // the log buffer offset + // + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)mStaticDataBuffer->Data; + DataBuf->LoggerInfo = LOGGER_INFO_FROM_PROTOCOL (LoggerProtocol); + DataBuf->ExpectedLogSize = EFI_PAGES_TO_SIZE (FixedPcdGet32 (PcdAdvancedLoggerPages)) - sizeof (ADVANCED_LOGGER_INFO); + DataBuf->ExpectedHeaderSize = EXPECTED_LOG_BUFFER_OFFSET (DataBuf->LoggerInfo); + if (!PrmConfigLibValidateInfoBlock (DataBuf)) { + DEBUG ((DEBUG_ERROR, "AdvLoggerOsConnectorPrmConfigLib Failed to validate AdvLogger region\n")); + Status = EFI_COMPROMISED_DATA; + goto Done; + } + + // + // Initialize the data buffer header + // + mStaticDataBuffer->Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE; + mStaticDataBuffer->Header.Length = (UINT32)DataBufferLength; + + // + // Allocate and populate the context buffer + // + + // + // This context buffer is not actually used by PRM handler at OS runtime. The OS will allocate + // the actual context buffer passed to the PRM handler. + // + // This context buffer is used internally in the firmware to associate a PRM handler with a + // a static data buffer and a runtime MMIO ranges array so those can be placed into the + // PRM_HANDLER_INFORMATION_STRUCT and PRM_MODULE_INFORMATION_STRUCT respectively for the PRM handler. + // + PrmContextBuffer = AllocateZeroPool (sizeof (*PrmContextBuffer)); + if (PrmContextBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + CopyGuid (&PrmContextBuffer->HandlerGuid, &mAdvLoggerOsConnectorPrmHandlerGuid); + PrmContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE; + PrmContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION; + + PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol)); + if (PrmConfigProtocol == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid); + PrmConfigProtocol->ModuleContextBuffers.BufferCount = 1; + PrmConfigProtocol->ModuleContextBuffers.Buffer = PrmContextBuffer; + PrmContextBuffer->StaticDataBuffer = mStaticDataBuffer; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AdvLoggerOsConnectorPrmVirtualAddressCallback, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + + // if we couldn't virtualize the address, we need to not publish the config protocol, as a physical + // address could point anywhere in kernel virtual space and we would give that to the caller or + // crash the system if it is unaccessible + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a failed to register for virtual address callback Status %r\n", __func__, Status)); + goto Done; + } + + // + // Install the PRM Configuration Protocol for this module. This indicates the configuration + // library has completed resource initialization for the PRM module. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mPrmConfigProtocolHandle, + &gPrmConfigProtocolGuid, + (VOID *)PrmConfigProtocol, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a failed to install config protocol\n", __func__)); + // if we fail to close the event, that's ok because in the event callback + // we check to see if mStaticDataBuffer is NULL, which in the error path + // we reset + gBS->CloseEvent (mVirtualAddressChangeEvent); + goto Done; + } + +Done: + if (EFI_ERROR (Status)) { + if ((DataBuf != NULL) && (DataBuf->LoggerInfo != NULL)) { + // if we have failed out, even though we are freeing the memory and should not + // have produced the config protocol, let's be sure not to pass the log pointer + // to ensure we don't have an invalid address that could be read + DataBuf->LoggerInfo = NULL; + } + + if (mStaticDataBuffer != NULL) { + FreePool (mStaticDataBuffer); + mStaticDataBuffer = NULL; + } + + if (PrmContextBuffer != NULL) { + FreePool (PrmContextBuffer); + } + + if (PrmConfigProtocol != NULL) { + FreePool (PrmConfigProtocol); + } + } + + // if we failed to setup the PRM, we should still boot as this is a diagnostic fetching mechanism + // we've logged (the log we won't be able to fetch) and that's all we can do + // however, we've freed the context buffer, so we won't be passing an invalid LoggerInfo pointer to the PRM module + return EFI_SUCCESS; +} diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf new file mode 100644 index 0000000000..fe6cab1ab6 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf @@ -0,0 +1,47 @@ +## @file AdvLoggerOsConnectorPrmConfigLib.inf +# AdvLoggerOsConnector PRM Configuration Library Instance +# +# This PRM configuration library instance is responsible for passing the AdvLogger in-memory log to the OsConnector PRM +# +# Copyright (c) Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.17 + BASE_NAME = AdvLoggerOsConnectorPrmConfigLib + FILE_GUID = 635DD215-6053-4ECA-887C-1E9BCFD60736 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|DXE_RUNTIME_DRIVER + CONSTRUCTOR = AdvLoggerOsConnectorPrmConfigLibConstructor + +[Sources] + AdvLoggerOsConnectorPrmConfigLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + PrmPkg/PrmPkg.dec + AdvLoggerPkg/AdvLoggerPkg.dec + +[Guids] + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gPrmConfigProtocolGuid + gAdvancedLoggerProtocolGuid + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeLib + DxeServicesTableLib + +[Pcd] + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPages diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.cpp b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.cpp new file mode 100644 index 0000000000..b256afa548 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.cpp @@ -0,0 +1,688 @@ +/** @file + + This unit tests the AdvLoggerOsConnectorPrmConfigLib + + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include + +extern "C" { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "../../../AdvLoggerOsConnectorPrm.h" + + extern PRM_DATA_BUFFER *mStaticDataBuffer; + + VOID + EFIAPI + AdvLoggerOsConnectorPrmVirtualAddressCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + + BOOLEAN + PrmConfigLibValidateInfoBlock ( + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf + ); + + EFI_STATUS + EFIAPI + AdvLoggerOsConnectorPrmConfigLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +} + +// *----------------------------------------------------------------------------------* +// * Test Contexts * +// *----------------------------------------------------------------------------------* + +using namespace testing; + +/// ================================================================================================ +/// ================================================================================================ +/// +/// TEST CASES +/// +/// ================================================================================================ +/// ================================================================================================ + +// +// Declarations for unit tests +// +class AdvLoggerPrmConfigLibTest : public Test { +protected: + MockUefiRuntimeLib UefiRuntimeLib; + MockMemoryAllocationLib MemoryAllocationLib; + MockUefiBootServicesTableLib UefiBootServicesTableLib; +}; + +/** + Unit test for AdvLoggerOsConnectorPrmVirtualAddressCallback. +**/ +TEST_F (AdvLoggerPrmConfigLibTest, AdvLoggerOsConnectorPrmVirtualAddressCallbackTests) { + PRM_DATA_BUFFER StaticDataBuffer; + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)&StaticDataBuffer.Data; + VOID **VirtualPointer = (VOID **)0xFFFFEEEEDDDDCCCC; + UINT64 DummyPtr = 0xDEADBEEFDEADBEEF; + + StaticDataBuffer.Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE; + StaticDataBuffer.Header.Length = sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER); + + // Test a NULL static data buffer + mStaticDataBuffer = NULL; + AdvLoggerOsConnectorPrmVirtualAddressCallback (NULL, NULL); + EXPECT_EQ (mStaticDataBuffer, (PRM_DATA_BUFFER *)NULL); + + // set mStaticDataBuffer to our copy + mStaticDataBuffer = &StaticDataBuffer; + + // test a successful pointer conversion + DataBuf->LoggerInfo = (ADVANCED_LOGGER_INFO *)DummyPtr; + DataBuf->ExpectedHeaderSize = 0xFFFF; + DataBuf->ExpectedLogSize = 0xAAAA; + EXPECT_CALL ( + UefiRuntimeLib, + EfiConvertPointer ( + 0, + Pointee (Eq ((VOID *)0xDEADBEEFDEADBEEF)) + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<1>(&VirtualPointer, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + AdvLoggerOsConnectorPrmVirtualAddressCallback (NULL, NULL); + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)mStaticDataBuffer->Data; + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)0xFFFFEEEEDDDDCCCC); + + // test unsuccessful pointer conversion + EXPECT_CALL ( + UefiRuntimeLib, + EfiConvertPointer ( + 0, + Pointee (Eq ((VOID *)0xFFFFEEEEDDDDCCCC)) + ) + ) + .WillOnce ( + Return (EFI_ABORTED) + ); + AdvLoggerOsConnectorPrmVirtualAddressCallback (NULL, NULL); + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)mStaticDataBuffer->Data; + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + EXPECT_EQ (DataBuf->ExpectedHeaderSize, 0U); + EXPECT_EQ (DataBuf->ExpectedLogSize, 0U); +} + +TEST_F (AdvLoggerPrmConfigLibTest, ValidateInfoBlockTests) { + ADV_LOGGER_PRM_DATA_BUFFER DataBuf; + BOOLEAN Result; + ADVANCED_LOGGER_INFO LoggerInfo; + + // Test NULL DataBuf + Result = PrmConfigLibValidateInfoBlock (NULL); + EXPECT_EQ (Result, FALSE); + + // Test NULL LoggerInfo + DataBuf.LoggerInfo = NULL; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test Bad LoggerInfo Signature + DataBuf.LoggerInfo = &LoggerInfo; + LoggerInfo.Signature = 0xDEADBEEF; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test bad LogBufferOffset + LoggerInfo.Signature = ADVANCED_LOGGER_SIGNATURE; + LoggerInfo.LogBufferOffset = 0xDEADBEEF; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test LogCurrentOffset > Total Log Size + LoggerInfo.LogBufferOffset = sizeof (LoggerInfo); + LoggerInfo.LogBufferSize = 0x1; + LoggerInfo.LogCurrentOffset = 0x7777; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test LogCurrentOffset < LogBufferOffset + LoggerInfo.LogBufferSize = 0x10000; + LoggerInfo.LogCurrentOffset = 0x3; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test ExpectedLogSize != LogBufferSize + DataBuf.ExpectedLogSize = 0x9999; + LoggerInfo.LogCurrentOffset = 0x150; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test ExpectedHeaderSize != LogBufferOffset + DataBuf.ExpectedHeaderSize = sizeof (LoggerInfo) - 0x10; + DataBuf.ExpectedLogSize = 0x10000; + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, FALSE); + + // Test success + DataBuf.ExpectedHeaderSize = sizeof (LoggerInfo); + Result = PrmConfigLibValidateInfoBlock (&DataBuf); + EXPECT_EQ (Result, TRUE); +} + +TEST_F (AdvLoggerPrmConfigLibTest, ConstructorTests) { + EFI_STATUS Status; + CHAR8 Buf[sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER)]; + CHAR8 ContextBuf[sizeof (PRM_CONTEXT_BUFFER)]; + CHAR8 ProtocolBuf[sizeof (PRM_CONFIG_PROTOCOL)]; + ADVANCED_LOGGER_PROTOCOL_CONTAINER LoggerProtocolContainer; + ADVANCED_LOGGER_INFO LoggerInfo; + ADVANCED_LOGGER_PROTOCOL *LoggerProtocol; + ADV_LOGGER_PRM_DATA_BUFFER *DataBuf; + + // test out of resources on mStaticDataBuffer + // for all of the constructor tests, we are expecting it to return SUCCESS, even in failure cases as + // this module is not required for boot. However, we want things safely cleaned up + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return ((VOID *)NULL) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + + // Test locate protocol failure + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + Return (EFI_NOT_FOUND) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + + // Fail validate Info Block + LoggerProtocolContainer.LoggerInfo = &LoggerInfo; + LoggerProtocol = &LoggerProtocolContainer.AdvLoggerProtocol; + DataBuf = (ADV_LOGGER_PRM_DATA_BUFFER *)((PRM_DATA_BUFFER *)Buf)->Data; + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + + // Fail to Allocate PrmContextBuffer + LoggerProtocolContainer.LoggerInfo = &LoggerInfo; + LoggerProtocol = &LoggerProtocolContainer.AdvLoggerProtocol; + LoggerProtocolContainer.AdvLoggerProtocol.Signature = ADVANCED_LOGGER_PROTOCOL_SIGNATURE; + LoggerProtocolContainer.AdvLoggerProtocol.Version = ADVANCED_LOGGER_PROTOCOL_VERSION; + LoggerInfo.Signature = ADVANCED_LOGGER_SIGNATURE; + LoggerInfo.LogBufferOffset = sizeof (LoggerInfo); + LoggerInfo.LogCurrentOffset = sizeof (LoggerInfo); + LoggerInfo.LogBufferSize = EFI_PAGES_TO_SIZE (FixedPcdGet32 (PcdAdvancedLoggerPages)) - sizeof (ADVANCED_LOGGER_INFO); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONTEXT_BUFFER) + ) + ) + .WillOnce ( + Return ((VOID *)NULL) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + + // fail to allocate PrmConfigProtocol + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONTEXT_BUFFER) + ) + ) + .WillOnce ( + Return (ContextBuf) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONFIG_PROTOCOL) + ) + ) + .WillOnce ( + Return ((VOID *)NULL) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (ContextBuf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + + // test CreateEventEx failure + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONTEXT_BUFFER) + ) + ) + .WillOnce ( + Return (ContextBuf) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONFIG_PROTOCOL) + ) + ) + .WillOnce ( + Return (ProtocolBuf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AdvLoggerOsConnectorPrmVirtualAddressCallback, + NULL, + BufferEq (&gEfiEventVirtualAddressChangeGuid, sizeof (EFI_GUID)), + _ + ) + ) + .WillOnce ( + Return (EFI_ABORTED) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (ContextBuf) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (ProtocolBuf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + + // Test InstallMultipleProtocolInterface failure + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONTEXT_BUFFER) + ) + ) + .WillOnce ( + Return (ContextBuf) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONFIG_PROTOCOL) + ) + ) + .WillOnce ( + Return (ProtocolBuf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AdvLoggerOsConnectorPrmVirtualAddressCallback, + NULL, + BufferEq (&gEfiEventVirtualAddressChangeGuid, sizeof (EFI_GUID)), + _ + ) + ) + .WillOnce ( + Return (EFI_SUCCESS) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_InstallProtocolInterface ( + _, + BufferEq (&gPrmConfigProtocolGuid, sizeof (EFI_GUID)), + EFI_NATIVE_INTERFACE, + Eq (ProtocolBuf) + ) + ) + .WillOnce ( + Return (EFI_ABORTED) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_CloseEvent ( + _ + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (Buf) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (ContextBuf) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + FreePool ( + Eq (ProtocolBuf) + ) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, (ADVANCED_LOGGER_INFO *)NULL); + + // Test success case + EXPECT_CALL ( + MemoryAllocationLib, + AllocateRuntimeZeroPool ( + sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (ADV_LOGGER_PRM_DATA_BUFFER) + ) + ) + .WillOnce ( + Return (Buf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_LocateProtocol ( + BufferEq (&gAdvancedLoggerProtocolGuid, sizeof (EFI_GUID)), + NULL, + _ + ) + ) + .WillOnce ( + DoAll ( + SetArgBuffer<2>(&LoggerProtocol, sizeof (VOID **)), + Return (EFI_SUCCESS) + ) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONTEXT_BUFFER) + ) + ) + .WillOnce ( + Return (ContextBuf) + ); + + EXPECT_CALL ( + MemoryAllocationLib, + AllocateZeroPool ( + sizeof (PRM_CONFIG_PROTOCOL) + ) + ) + .WillOnce ( + Return (ProtocolBuf) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AdvLoggerOsConnectorPrmVirtualAddressCallback, + NULL, + BufferEq (&gEfiEventVirtualAddressChangeGuid, sizeof (EFI_GUID)), + _ + ) + ) + .WillOnce ( + Return (EFI_SUCCESS) + ); + + EXPECT_CALL ( + UefiBootServicesTableLib, + gBS_InstallProtocolInterface ( + _, + BufferEq (&gPrmConfigProtocolGuid, sizeof (EFI_GUID)), + EFI_NATIVE_INTERFACE, + Eq (ProtocolBuf) + ) + ) + .WillOnce ( + Return (EFI_SUCCESS) + ); + + Status = AdvLoggerOsConnectorPrmConfigLibConstructor (NULL, NULL); + EXPECT_EQ (Status, EFI_SUCCESS); + EXPECT_EQ (DataBuf->LoggerInfo, &LoggerInfo); +} + +int +main ( + int argc, + char *argv[] + ) +{ + testing::InitGoogleTest (&argc, argv); + return RUN_ALL_TESTS (); +} diff --git a/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.inf b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.inf new file mode 100644 index 0000000000..5b7a3c3787 --- /dev/null +++ b/AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.inf @@ -0,0 +1,44 @@ +## @file AdvLoggerPrmConfigLibGoogleTest.inf +# +# This unit tests the AdvLoggerOsConnectorPrmConfigLib +# +# Copyright (c) Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AdvLoggerPrmConfigLibGoogleTest + FILE_GUID = 2BEEEDEF-618B-44E3-A051-87DC43C5689E + MODULE_TYPE = HOST_APPLICATION + VERSION_STRING = 1.0 + +[Sources] + AdvLoggerPrmConfigLibGoogleTest.cpp + ../AdvLoggerOsConnectorPrmConfigLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + AdvLoggerPkg/AdvLoggerPkg.dec + PrmPkg/PrmPkg.dec + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec + +[LibraryClasses] + GoogleTestLib + UefiRuntimeLib + UefiBootServicesTableLib + +# Library Instance Reqs +[Pcd] + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPages + +[Guids] + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gPrmConfigProtocolGuid + gAdvancedLoggerProtocolGuid + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /std:c++latest diff --git a/AdvLoggerPkg/AdvLoggerPkg.ci.yaml b/AdvLoggerPkg/AdvLoggerPkg.ci.yaml index b02dab1e8b..644530283c 100644 --- a/AdvLoggerPkg/AdvLoggerPkg.ci.yaml +++ b/AdvLoggerPkg/AdvLoggerPkg.ci.yaml @@ -15,7 +15,7 @@ ## options defined ci/Plugin/CharEncodingCheck "CharEncodingCheck": { - "IgnoreFiles": [] + "IgnoreFiles": ["Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf"] }, ## options defined ci/Plugin/DependencyCheck @@ -27,9 +27,11 @@ "AdvLoggerPkg/AdvLoggerPkg.dec", "MsWheaPkg/MsWheaPkg.dec", "PolicyServicePkg/PolicyServicePkg.dec", - "ShellPkg/ShellPkg.dec" + "ShellPkg/ShellPkg.dec", + "PrmPkg/PrmPkg.dec" ], "AcceptableDependencies-HOST_APPLICATION":[ # for host based unit tests + "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" ], "AcceptableDependencies-UEFI_APPLICATION": [ ], @@ -46,10 +48,21 @@ "GuidCheck": { "IgnoreGuidName": [], "IgnoreGuidValue": [], - "IgnoreFoldersAndFiles": [], + "IgnoreFoldersAndFiles": ["**/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf"], "IgnoreDuplicates": [] }, + ## options defined ci/Plugin/HostUnitTestCompilerPlugin + "HostUnitTestCompilerPlugin": { + "DscPath": "Test/AdvLoggerHostTest.dsc" + }, + + ## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck + "HostUnitTestDscCompleteCheck": { + "IgnoreInf": [], + "DscPath": "Test/AdvLoggerHostTest.dsc" + }, + ## options defined ci/Plugin/LibraryClassCheck "LibraryClassCheck": { "IgnoreLibraryClass": [], @@ -59,7 +72,7 @@ ## options defined ci/Plugin/SpellCheck "SpellCheck": { "AuditOnly": False, # Fails test but run in AuditOnly mode to collect log - "IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files + "IgnoreFiles": ["Application/Windows/PrmFuncSample/**"], # use gitignore syntax to ignore errors in matching files "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore "AdditionalIncludePaths": [], # Additional paths to spell check (wildcards supported) "ExtendWords": [ diff --git a/AdvLoggerPkg/AdvLoggerPkg.dec b/AdvLoggerPkg/AdvLoggerPkg.dec index 770d0bc300..f4bfd2589f 100644 --- a/AdvLoggerPkg/AdvLoggerPkg.dec +++ b/AdvLoggerPkg/AdvLoggerPkg.dec @@ -98,7 +98,7 @@ # gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedFileLoggerForceEnable|TRUE|BOOLEAN|0x00010184 - ## PcdAdvancedLoggerAutoWrapEnable - Automatically wrap around the LogCurrent cursor when it reaches the end + ## PcdAdvancedLoggerAutoWrapEnable - Automatically wrap around the LogCurrentOffset cursor when it reaches the end # of the log. This feature only activates at runtime (after exit boot service event). # gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerAutoWrapEnable|FALSE|BOOLEAN|0x00010188 diff --git a/AdvLoggerPkg/AdvLoggerPkg.dsc b/AdvLoggerPkg/AdvLoggerPkg.dsc index a3b4601850..b4ea95a665 100644 --- a/AdvLoggerPkg/AdvLoggerPkg.dsc +++ b/AdvLoggerPkg/AdvLoggerPkg.dsc @@ -115,6 +115,8 @@ [Components] AdvLoggerPkg/Library/BaseDebugLibAdvancedLogger/BaseDebugLibAdvancedLogger.inf AdvLoggerPkg/Library/BasePanicLibAdvancedLogger/BasePanicLibAdvancedLogger.inf + AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf + AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf [Components.IA32] AdvLoggerPkg/Library/AdvancedLoggerLib/Pei/AdvancedLoggerLib.inf diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.c b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.c new file mode 100644 index 0000000000..863afbede2 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.c @@ -0,0 +1,238 @@ +/*-- + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + +Module Name: + + PrmFuncSample.c + +Abstract: + + This module implements a sample that utilizes the + Windows PRM direct call interface. + +Environment: + + Kernel mode only. + +--*/ + +#include "prmfuncsample.h" + +HANDLE FileHandle = NULL; + +VOID +EvtDriverUnload ( + WDFDRIVER Driver + ) +{ + UNREFERENCED_PARAMETER (Driver); + return; +} + +NTSTATUS +DriverEntry ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) + +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry configures and creates a WDF driver + object. + . +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG Config; + WDFDRIVER Driver; + NTSTATUS Status; + PRM_DIRECT_CALL_PARAMETERS TestParameters; + PRM_INTERFACE PrmInterface; + ULONG64 EfiStatus; + BOOLEAN Found; + ADVANCED_LOGGER_PRM_PARAMETER_BUFFER *ParamBuf; + VOID *KernelBuf = NULL; + UNICODE_STRING filePath; + OBJECT_ATTRIBUTES objAttr; + HANDLE fileHandle; + IO_STATUS_BLOCK ioStatus; + UINT32 BufSize = 0; + + KdPrint (("PRM Function Test Driver - Driver Framework Edition.\n")); + + // Initialize the driver configuration structure + WDF_DRIVER_CONFIG_INIT (&Config, WDF_NO_EVENT_CALLBACK); + + // Register the EvtDriverUnload callback + Config.EvtDriverUnload = EvtDriverUnload; + Config.DriverInitFlags = WdfDriverInitNonPnpDriver; + + // + // Create a framework driver object to represent our driver. + // + + Status = WdfDriverCreate ( + DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, // Driver Attributes + &Config, // Driver Config Info + &Driver + ); + + if (!NT_SUCCESS (Status)) { + KdPrint (("WdfDriverCreate failed with status 0x%x\n", Status)); + return Status; + } + + TestParameters.Guid = GUID_ADVLOGGER_PRM_HANDLER; + ParamBuf = (ADVANCED_LOGGER_PRM_PARAMETER_BUFFER *)&(TestParameters.ParameterBuffer); + ParamBuf->OutputBuffer = NULL; + ParamBuf->OutputBufferSize = &BufSize; + + // + // Acquire the direct-call PRM interface, which is defined in + // prminterface.h. + // + // typedef struct _PRM_INTERFACE { + // ULONG Version; + // PPRM_UNLOCK_MODULE UnlockModule; + // PPRM_LOCK_MODULE LockModule; + // PPRM_INVOKE_HANDLER InvokeHandler; + // PPRM_QUERY_HANDLER QueryHandler; + // } PRM_INTERFACE, *PPRM_INTERFACE; + // + + Status = ExGetPrmInterface (1, &PrmInterface); + if (!NT_SUCCESS (Status)) { + return Status; + } + + // + // Lock the handler's PRM module to synchronize against any potential + // runtime update to the PRM module. + // + // N.B. Note that technically this is only needed if a series of PRM + // handlers need to be called transactionally (thus preventing + // interleaving of PRM module updates). However, we will do it here + // as an example of how it could be done. + // + + Status = PrmInterface.LockModule ( + (LPGUID)&TestParameters.Guid + ); + + if (!NT_SUCCESS (Status)) { + return Status; + } + + // + // Query for the presence of the PRM handler. + // + + Status = PrmInterface.QueryHandler ( + (LPGUID)&TestParameters.Guid, + &Found + ); + + if ((!NT_SUCCESS (Status)) || (Found == FALSE)) { + return Status; + } + + // + // Invoke the PRM handler + // + + Status = PrmInterface.InvokeHandler ( + (LPGUID)&TestParameters.Guid, + TestParameters.ParameterBuffer, + 0, + &EfiStatus + ); + + if (!NT_SUCCESS (Status)) { + return Status; + } + + if ((EfiStatus == EFI_BUFFER_TOO_SMALL) || (EfiStatus == EFI_BUFFER_TOO_SMALL_TRUNCATED)) { + // ParamBuf now has the right size to alloc + KernelBuf = ExAllocatePool2 (POOL_FLAG_NON_PAGED, BufSize, 'prmf'); + if (KernelBuf == NULL) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + ParamBuf->OutputBuffer = KernelBuf; + + Status = PrmInterface.InvokeHandler ( + (LPGUID)&TestParameters.Guid, + TestParameters.ParameterBuffer, + 0, + &EfiStatus + ); + + if (!NT_SUCCESS (Status)) { + return Status; + } + + if (EfiStatus == 0) { + RtlInitUnicodeString (&filePath, L"\\??\\C:\\AdvLogger.log"); + InitializeObjectAttributes (&objAttr, &filePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + Status = ZwCreateFile ( + &fileHandle, + FILE_GENERIC_WRITE, + &objAttr, + &ioStatus, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OVERWRITE_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + + if (NT_SUCCESS (Status)) { + // Write the buffer to the file + Status = ZwWriteFile (fileHandle, NULL, NULL, NULL, &ioStatus, KernelBuf, BufSize, NULL, NULL); + ZwClose (fileHandle); + } + } + } + + // + // Unlock the PRM module + // + // N.B. Note that technically this is only needed if a series of PRM + // handlers need to be called as part of transaction. However, we will + // do it here as an example of how it could be done. + // + + Status = PrmInterface.UnlockModule ( + (LPGUID)&TestParameters.Guid + ); + + return Status; +} diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.h b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.h new file mode 100644 index 0000000000..2aa4bf659a --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.h @@ -0,0 +1,74 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + prmfuncsample.h + +Environment: + + Kernel mode + +--*/ + +#if !defined (_PRMFUNCTEST_H_) +#define _PRMFUNCTEST_H_ + +#include +#include + +#define NTSTRSAFE_LIB +#include +#include +#include + +#define PRMFUNCTEST_POOL_TAG (ULONG) 'fmrP' +// this is because of a bug in some versions of Windows where the EfiStatus gets truncated to a UINT32 +#define EFI_BUFFER_TOO_SMALL_TRUNCATED 0x5 +#define EFI_BUFFER_TOO_SMALL 0x8000000000000005 + +DEFINE_GUID ( + GUID_ADVLOGGER_PRM_HANDLER, + 0x0f8aef11, + 0x77b8, + 0x4d7f, + 0x84, + 0xcc, + 0xfe, + 0x0c, + 0xce, + 0x64, + 0xac, + 0x14 + ); + +#define PRM_PARAMETER_BUFFER_SIZE 308 + +typedef struct _PRM_TEST_PARAMETERS { + GUID Guid; + UCHAR ParameterBuffer[PRM_PARAMETER_BUFFER_SIZE]; +} PRM_TEST_PARAMETERS, *PPRM_TEST_PARAMETERS; + +typedef struct _PRM_DIRECT_CALL_PARAMETERS { + GUID Guid; + UCHAR ParameterBuffer[PRM_PARAMETER_BUFFER_SIZE]; +} PRM_DIRECT_CALL_PARAMETERS, *PPRM_DIRECT_CALL_PARAMETERS; + +typedef struct _PRM_TEST_RESULT { + NTSTATUS Status; + ULONG64 EfiStatus; + UCHAR Buffer[PRM_PARAMETER_BUFFER_SIZE]; +} PRM_TEST_RESULT, *PPRM_TEST_RESULT; + +typedef struct { + VOID *OutputBuffer; + UINT32 *OutputBufferSize; +} ADVANCED_LOGGER_PRM_PARAMETER_BUFFER; + +#endif diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf new file mode 100644 index 0000000000..502478dbe9 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.inf @@ -0,0 +1,55 @@ +[Version] +Signature="$WINDOWS NT$" +Class=System +ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} +Provider=%ProviderName% +DriverVer=2/1/2023 +CatalogFile=prmfuncsample.cat +PnpLockdown=1 + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +prmfuncsample.sys = 1,, + +[DestinationDirs] +Drivers_Dir = 13 + +[ControlFlags] +ExcludeFromSelect = * + +[Manufacturer] +%ManufacturerName%=Standard,NT$ARCH$.10.0...26048 + +[Standard.NT$ARCH$.10.0...26048] +%PMT10000.DeviceDesc% = PrmFuncSample_Inst,*PMT10000 + +[PrmFuncSample_Inst.NT.Services] +AddService = PrmFuncSample,%SPSVCINST_ASSOCSERVICE%,PrmFuncSample_Service_Inst + +[PrmFuncSample_Inst.NT] +CopyFiles = Drivers_Dir + +[Drivers_Dir] +prmfuncsample.sys + +[PrmFuncSample_Service_Inst] +DisplayName = %PRMFUNCSAMPLE.SvcDesc% +ServiceType = %SERVICE_KERNEL_DRIVER% +StartType = %SERVICE_SYSTEM_START% +ErrorControl = %SERVICE_ERROR_NORMAL% +ServiceBinary = %13%\prmfuncsample.sys +LoadOrderGroup = Extended Base + +[strings] +ProviderName = "TODO-Set-Provider" +ManufacturerName = "TODO-Set-Manufacturer" +DiskId1 = "PRM Func Sample Driver Installation Disk #1" +PMT10000.DeviceDesc = "PRM Func Sample Device" +PRMFUNCSAMPLE.SvcDesc = "PRM Func Sample Driver" + +SPSVCINST_ASSOCSERVICE = 0x00000002 +SERVICE_KERNEL_DRIVER = 1 +SERVICE_SYSTEM_START = 1 +SERVICE_ERROR_NORMAL = 1 diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj new file mode 100644 index 0000000000..42e2764953 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x64 + + + Release + x64 + + + + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4} + + + + Windows10 + False + Desktop + KMDF + WindowsKernelModeDriver10.0 + Driver + + + Windows10 + False + Desktop + KMDF + WindowsKernelModeDriver10.0 + Driver + + + Windows10 + True + Desktop + KMDF + WindowsKernelModeDriver10.0 + Driver + + + Windows10 + True + Desktop + KMDF + WindowsKernelModeDriver10.0 + Driver + + + + $(IntDir) + + + + + + + + + + + + + + + + * + true + $(InfArch) + true + .\$(IntDir)\prmfuncsample.inf + + + + prmfuncsample + + + prmfuncsample + + + prmfuncsample + + + prmfuncsample + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\ntoskrnl.lib + + + true + Level4 + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(KIT_SHARED_INC_PATH_WDK) + + + sha256 + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\ntoskrnl.lib + + + true + Level4 + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(KIT_SHARED_INC_PATH_WDK) + + + sha256 + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\ntoskrnl.lib + + + true + Level4 + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(KIT_SHARED_INC_PATH_WDK) + + + sha256 + + + + + %(AdditionalDependencies);$(DDK_LIB_PATH)\ksguid.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\ntoskrnl.lib + + + true + Level4 + + + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(KIT_SHARED_INC_PATH_WDK) + + + sha256 + + + + + + + + + + + + + + + + + + + diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj.Filters b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj.Filters new file mode 100644 index 0000000000..ba89a44965 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/PrmFunc/prmfuncsample.vcxproj.Filters @@ -0,0 +1,31 @@ + + + + + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* + {E10CB9FB-4852-4353-85F5-667D4D2A13DD} + + + h;hpp;hxx;hm;inl;inc;xsd + {EC8940D8-5E2B-49AB-AB85-7CABCAE698D1} + + + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml + {42A1FDF4-6DB4-41B2-9423-8002A20D1B0D} + + + inf;inv;inx;mof;mc; + {FD9F921C-D1EF-421B-A692-F23423B32E64} + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/README.md b/AdvLoggerPkg/Application/Windows/PrmFuncSample/README.md new file mode 100644 index 0000000000..034a3c61fd --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/README.md @@ -0,0 +1,41 @@ +# Advanced Logger PRM Sample Driver + +The Advanced Logger PRM sample driver demonstrates how to write a KMDF driver to utlize the Windows Platform Runtime +Mechanism (PRM) direct-call interface to talk to the [Advanced Logger PRM](../../../AdvLoggerOsConnectorPrm) +to fetch the log and write it to a file. + +This driver is based on the Windows Driver Sample [PrmFuncSample driver](https://github.com/microsoft/Windows-driver-samples/tree/develop/prm). + +## Building + +*Note* This driver requires a Windows SDK greater than 10.0.22621 (which as of this writing is what is publicly +available) to access PRM structures that were not previously available. + +Open prmsample.sln in Visual Studio 2022. Ensure you have the Windows SDK and WDK installed as well as the MSVC build +tools for your architecture. Click Build->Build Solution. + +## Running + +Copy the output binaries to the target system. Start the driver by opening Cmd Prompt and running: + +- `sc create PrmSample binPath="{PATH_TO_BINS/prmfuncsample.sys}" type=kernel` +- `sc start PrmSample` + +The driver will write the log to `C:\AdvLogger.log`. You can then use [DecodeUefiLog.py](../../DecodeUefiLog/ReadMe.md) +to decode the log. + +You can unload the driver by doing: + +- `sc stop PrmSample` + +Further loading of the driver will fetch the current log and overwrite `C:\AdvLogger.log`. + +## Consumption + +This driver is only written as a sample. To access the Adv Logger PRM in your own code, copy the patterns this sample +driver does to communicate with PRM.sys. Your driver can link up to an application to be driven or be a standalone +driver. + +## Related topics + +[Platform Runtime Mechanism Specification](https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf/) diff --git a/AdvLoggerPkg/Application/Windows/PrmFuncSample/prmsample.sln b/AdvLoggerPkg/Application/Windows/PrmFuncSample/prmsample.sln new file mode 100644 index 0000000000..b68cf27e4f --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/PrmFuncSample/prmsample.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34414.90 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "prmfuncsample", "prmfunc\prmfuncsample.vcxproj", "{A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Debug|ARM64.Build.0 = Debug|ARM64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Release|ARM64.ActiveCfg = Release|ARM64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Release|ARM64.Build.0 = Release|ARM64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Debug|x64.ActiveCfg = Debug|x64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Debug|x64.Build.0 = Debug|x64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Debug|x64.Deploy.0 = Debug|x64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Release|x64.ActiveCfg = Release|x64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Release|x64.Build.0 = Release|x64 + {A80FE9DD-C140-40F6-A3F4-55A2A55BFAD4}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E71959C9-929E-4552-B267-ED7ABEE1B330} + EndGlobalSection +EndGlobal diff --git a/AdvLoggerPkg/Docs/ReadMe.md b/AdvLoggerPkg/Docs/ReadMe.md index 7408aad58b..0d67369642 100644 --- a/AdvLoggerPkg/Docs/ReadMe.md +++ b/AdvLoggerPkg/Docs/ReadMe.md @@ -245,13 +245,61 @@ and the follow change is needed in the .fdf: ## Advanced Logger Retrieval From Windows -The Advanced Logger can be retrieved from Windows using the [DecodeUefiLog](../Application/DecodeUefiLog/ReadMe.md) +### GetVariable Interface + +The Advanced Logger log can be retrieved from Windows using the [DecodeUefiLog](../Application/DecodeUefiLog/ReadMe.md) python utility. The utility runs under windows and retrieves the log through the `AdvLoggerAccessLib` instance provided by the platform. If reading of the log fails, please verify that the `AdvLoggerAccessLib` instance in the platform is either the `AdvLoggerMmAccessLib` or the `AdvLoggerSmmAccessLib` and not the NULL instance provided by MdeModulePkg. +### PRM Interface + +The Advanced Logger log can also be retrieved from the [Advanced Logger PRM](../AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.c). +The advantage of the PRM over the GetVariable interface is that it avoids SMM and/or Trust Zone, depending on +architecture. This means all the cores do not need to quiesce to fetch the log. In addition, the PRM interface is +independently serviceable from the OS. + +To include the PRM in your FW, add the following to your DSC: + +```inf +# PRM Configuration Driver + PrmPkg/PrmConfigDxe/PrmConfigDxe.inf { + + NULL|AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/AdvLoggerOsConnectorPrmConfigLib.inf + } + + # PRM Module Loader Driver + PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf + + # PRM SSDT Installation Driver + PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf + + # Adv Logger PRM Module + AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf +``` + +And the following to your FDF: + +```inf +# PRM Configuration Driver +INF PrmPkg/PrmConfigDxe/PrmConfigDxe.inf + +# Adv Logger PRM Module +INF AdvLoggerPkg/AdvLoggerOsConnectorPrm/AdvLoggerOsConnectorPrm.inf + +# PRM Module Loader Driver +INF PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf + +# PRM SSDT Installation Driver +INF PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf +``` + +The PRM log can be fetched via an OS driver. See the [Windows sample](../Application/Windows/PrmFuncSample/README.md). + +See [PrmPkg](https://github.com/microsoft/mu_tiano_plus/blob/HEAD/PrmPkg/Readme.md) for more details. + ## Hardware Logging Level The v3 data header supports a new field of hardware debugging level to support setting the serial print configurable diff --git a/AdvLoggerPkg/Test/AdvLoggerHostTest.dsc b/AdvLoggerPkg/Test/AdvLoggerHostTest.dsc new file mode 100644 index 0000000000..08fafca0de --- /dev/null +++ b/AdvLoggerPkg/Test/AdvLoggerHostTest.dsc @@ -0,0 +1,47 @@ +## @file +# Host Test DSC for the Advanced Logger Package +# +# Copyright (c) Microsoft Corporation +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +################################################################################ +[Defines] + PLATFORM_NAME = AdvLoggerPkgHostTest + PLATFORM_GUID = 1BF313CF-F093-42A9-8676-3445F2544295 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/AdvLoggerPkg + SUPPORTED_ARCHITECTURES = IA32|X64 + SKUID_IDENTIFIER = DEFAULT + BUILD_TARGETS = NOOPT + +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses.common.HOST_APPLICATION] + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + + # + # Mocked Libs + # + UefiRuntimeLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeLib/MockUefiRuntimeLib.inf + MemoryAllocationLib|MdePkg/Test/Mock/Library/GoogleTest/MockMemoryAllocationLib/MockMemoryAllocationLib.inf + UefiBootServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf + +################################################################################ +# +# Components section - list of all Components needed by this Platform. +# +################################################################################ +[Components] + AdvLoggerPkg/AdvLoggerOsConnectorPrm/Library/AdvLoggerOsConnectorPrmConfigLib/GoogleTest/AdvLoggerPrmConfigLibGoogleTest.inf + AdvLoggerPkg/AdvLoggerOsConnectorPrm/GoogleTest/AdvLoggerOsConnectorPrmGoogleTest.inf