* [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol
@ 2022-10-10 13:52 Jason Lou
2022-10-14 6:18 ` Ni, Ray
0 siblings, 1 reply; 2+ messages in thread
From: Jason Lou @ 2022-10-10 13:52 UTC (permalink / raw)
To: devel; +Cc: Jason Lou, Ray Ni, Eric Dong, Laszlo Ersek, Rahul Kumar
From: Jason Lou <yun.lou@intel.com>
The code changes add unit tests based on current UnitTestFramework.
EdkiiPeiMpServices2PpiPeiUnitTest PEI module is used to test
EdkiiPeiMpServices2Ppi and EfiMpServiceProtocolDxeUnitTest DXE driver is
used to test EfiMpServiceProtocol.
Signed-off-by: Jason Lou <yun.lou@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
---
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c | 477 ++++++
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c | 244 +++
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c | 1776 ++++++++++++++++++++
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf | 46 +
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf | 46 +
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h | 627 +++++++
UefiCpuPkg/UefiCpuPkg.dsc | 5 +
7 files changed, 3221 insertions(+)
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c
new file mode 100644
index 0000000000..5c42a81d29
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c
@@ -0,0 +1,477 @@
+/** @file
+ PEI Module to test APIs defined in EdkiiPeiMpServices2Ppi.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include "EfiMpServicesUnitTestCommom.h"
+
+#define UNIT_TEST_NAME "EdkiiPeiMpServices2Ppi Unit Test"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Get EDKII_PEI_MP_SERVICES2_PPI pointer.
+
+ @param[out] MpServices Pointer to the buffer where EDKII_PEI_MP_SERVICES2_PPI is stored.
+
+ @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is returned
+ @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not found
+**/
+EFI_STATUS
+MpServicesUnitTestGetMpServices (
+ OUT MP_SERVICES *MpServices
+ )
+{
+ return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOID **)&MpServices->Ppi);
+}
+
+/**
+ Retrieve the number of logical processor in the platform and the number of those logical processors that
+ are enabled on this boot.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
+ the BSP and disabled APs.
+ @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
+
+ @retval EFI_SUCCESS Retrieve the number of logical processor successfully
+ @retval Others Retrieve the number of logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetNumberOfProcessors (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ )
+{
+ return MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, NumberOfProcessors, NumberOfEnabledProcessors);
+}
+
+/**
+ Get detailed information on the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the processor.
+ @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
+
+ @retval EFI_SUCCESS Get information on the requested logical processor successfully
+ @retval Others Get information on the requested logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ return MpServices.Ppi->GetProcessorInfo (MpServices.Ppi, ProcessorNumber, ProcessorInfoBuffer);
+}
+
+/**
+ Execute a caller provided function on all enabled APs.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
+ one by one, in ascending order of processor handle number.
+ If FALSE, then all the enabled APs execute the function specified by Procedure
+ simultaneously.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+ @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
+ @retval Others Execute a caller provided function on all enabled APs unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupAllAPs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ )
+{
+ return MpServices.Ppi->StartupAllAPs (MpServices.Ppi, Procedure, SingleThread, TimeoutInMicroSeconds, ProcedureArgument);
+}
+
+/**
+ Caller gets one enabled AP to execute a caller-provided function.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+
+ @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
+ @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupThisAP (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ )
+{
+ return MpServices.Ppi->StartupThisAP (MpServices.Ppi, Procedure, ProcessorNumber, TimeoutInMicroSeconds, ProcedureArgument);
+}
+
+/**
+ Switch the requested AP to be the BSP from that point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
+ @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
+
+ @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
+ @retval Others Switch the requested AP to be the BSP unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestSwitchBSP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ return MpServices.Ppi->SwitchBSP (MpServices.Ppi, ProcessorNumber, EnableOldBSP);
+}
+
+/**
+ Caller enables or disables an AP from this point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
+ @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
+
+ @retval EFI_SUCCESS Caller enables or disables an AP successfully.
+ @retval Others Caller enables or disables an AP unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestEnableDisableAP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag
+ )
+{
+ return MpServices.Ppi->EnableDisableAP (MpServices.Ppi, ProcessorNumber, EnableAP, HealthFlag);
+}
+
+/**
+ Get the handle number for the calling processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] ProcessorNumber The handle number for the calling processor.
+
+ @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
+ @retval Others Get the handle number for the calling processor unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestWhoAmI (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *ProcessorNumber
+ )
+{
+ return MpServices.Ppi->WhoAmI (MpServices.Ppi, ProcessorNumber);
+}
+
+/**
+ Execute a caller provided function on all enabled CPUs.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled CPUs of the system.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all enabled CPUs.
+
+ @retval EFI_SUCCESS Execute a caller provided function on all enabled CPUs successfully
+ @retval Others Execute a caller provided function on all enabled CPUs unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupAllCPUs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ )
+{
+ return MpServices.Ppi->StartupAllCPUs (MpServices.Ppi, Procedure, TimeoutInMicroSeconds, ProcedureArgument);
+}
+
+/**
+ Infinite loop procedure to be run on specified AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+ApInfiniteLoopProcedure (
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ volatile BOOLEAN InfiniteLoop;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ if (ProcessorNumber == LocalContext->BspNumber) {
+ InfiniteLoop = FALSE;
+ } else {
+ InfiniteLoop = TRUE;
+ }
+
+ while (InfiniteLoop) {
+ }
+}
+
+/**
+ Procedure to run MP service StartupAllCPUs on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceStartupAllCPUsOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupAllCPUs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ 0,
+ NULL
+ );
+}
+
+/**
+ Unit test of PEI MP service StartupAllCPU.
+ All CPUs should execute the Procedure.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllCPUs1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF);
+ Status = MpServicesUnitTestStartupAllCPUs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreCpuNumbers,
+ 0,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
+ UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of PEI MP service StartupAllCPU.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllCPUs2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceStartupAllCPUsOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of PEI MP service StartupAllCPU.
+ When called with all CPUs timeout, the return status should be EFI_TIMEOUT.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllCPUs3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ Status = MpServicesUnitTestStartupAllCPUs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)ApInfiniteLoopProcedure,
+ RUN_PROCEDURE_TIMEOUT_VALUE,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Create test suite and unit tests only for EdkiiPeiMpServices2Ppi.
+
+ @param[in] Framework A pointer to the framework that is being persisted.
+ @param[in] Context A pointer to the private data buffer.
+
+ @retval EFI_SUCCESS Create test suite and unit tests successfully.
+ @retval Others Create test suite and unit tests unsuccessfully.
+**/
+EFI_STATUS
+AddTestCaseOnlyForEdkiiPeiMpServices2Ppi (
+ IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
+ IN MP_SERVICE_UT_CONTEXT *Context
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_SUITE_HANDLE MpServiceStartupAllCPUsTestSuite;
+
+ MpServiceStartupAllCPUsTestSuite = NULL;
+
+ //
+ // Test StartupAllCPUs function
+ //
+ Status = CreateUnitTestSuite (&MpServiceStartupAllCPUsTestSuite, Framework, "Execute a caller provided function on all enabled CPUs", "MpServices.StartupAllCPUs", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupAllCPUs Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 1", "TestStartupAllCPUs1", TestStartupAllCPUs1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 2", "TestStartupAllCPUs2", TestStartupAllCPUs2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 3", "TestStartupAllCPUs3", TestStartupAllCPUs3, InitUTContext, CheckUTContext, Context);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Standard PEIM entry point for unit test execution from PEI.
+ Initialize the unit test framework, suite, and unit tests for the EdkiiPeiMpServices2Ppi and run the unit test.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Pointer to PEI Services table.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ MP_SERVICE_UT_CONTEXT Context;
+
+ Framework = NULL;
+ Context.MpServices.Ppi = NULL;
+ Context.CommonBuffer = NULL;
+ Context.DisabledApNumber = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Create test suite and unit tests only for EdkiiPeiMpServices2Ppi.
+ //
+ Status = AddTestCaseOnlyForEdkiiPeiMpServices2Ppi (Framework, &Context);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in AddTestCaseOnlyForEdkiiPeiMpServices2Ppi. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
+ //
+ Status = AddCommonTestCase (Framework, &Context);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework != NULL) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c
new file mode 100644
index 0000000000..57f8ba3c06
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c
@@ -0,0 +1,244 @@
+/** @file
+ PEI Module to test EfiMpServiceProtocol.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include "EfiMpServicesUnitTestCommom.h"
+
+#define UNIT_TEST_NAME "EfiMpServiceProtocol Unit Test"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Get EFI_MP_SERVICES_PROTOCOL pointer.
+
+ @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored
+
+ @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned
+ @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found
+**/
+EFI_STATUS
+MpServicesUnitTestGetMpServices (
+ OUT MP_SERVICES *MpServices
+ )
+{
+ return gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices->Protocol);
+}
+
+/**
+ Retrieve the number of logical processor in the platform and the number of those logical processors that
+ are enabled on this boot.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
+ the BSP and disabled APs.
+ @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
+
+ @retval EFI_SUCCESS Retrieve the number of logical processor successfully
+ @retval Others Retrieve the number of logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetNumberOfProcessors (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ )
+{
+ return MpServices.Protocol->GetNumberOfProcessors (MpServices.Protocol, NumberOfProcessors, NumberOfEnabledProcessors);
+}
+
+/**
+ Get detailed information on the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the processor.
+ @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
+
+ @retval EFI_SUCCESS Get information on the requested logical processor successfully
+ @retval Others Get information on the requested logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ return MpServices.Protocol->GetProcessorInfo (MpServices.Protocol, ProcessorNumber, ProcessorInfoBuffer);
+}
+
+/**
+ Execute a caller provided function on all enabled APs.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
+ one by one, in ascending order of processor handle number.
+ If FALSE, then all the enabled APs execute the function specified by Procedure
+ simultaneously.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+ @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
+ @retval Others Execute a caller provided function on all enabled APs unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupAllAPs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ )
+{
+ return MpServices.Protocol->StartupAllAPs (MpServices.Protocol, Procedure, SingleThread, NULL, TimeoutInMicroSeconds, ProcedureArgument, NULL);
+}
+
+/**
+ Caller gets one enabled AP to execute a caller-provided function.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+
+ @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
+ @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupThisAP (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ )
+{
+ return MpServices.Protocol->StartupThisAP (MpServices.Protocol, Procedure, ProcessorNumber, NULL, TimeoutInMicroSeconds, ProcedureArgument, NULL);
+}
+
+/**
+ Switch the requested AP to be the BSP from that point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
+ @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
+
+ @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
+ @retval Others Switch the requested AP to be the BSP unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestSwitchBSP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ return MpServices.Protocol->SwitchBSP (MpServices.Protocol, ProcessorNumber, EnableOldBSP);
+}
+
+/**
+ Caller enables or disables an AP from this point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
+ @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
+
+ @retval EFI_SUCCESS Caller enables or disables an AP successfully.
+ @retval Others Caller enables or disables an AP unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestEnableDisableAP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag
+ )
+{
+ return MpServices.Protocol->EnableDisableAP (MpServices.Protocol, ProcessorNumber, EnableAP, HealthFlag);
+}
+
+/**
+ Get the handle number for the calling processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] ProcessorNumber The handle number for the calling processor.
+
+ @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
+ @retval Others Get the handle number for the calling processor unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestWhoAmI (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *ProcessorNumber
+ )
+{
+ return MpServices.Protocol->WhoAmI (MpServices.Protocol, ProcessorNumber);
+}
+
+/**
+ Standard DXE driver or UEFI application entry point for unit test execution from DXE or UEFI Shell.
+ Initialize the unit test framework, suite, and unit tests for the EfiMpServiceProtocol and run the unit test.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ MP_SERVICE_UT_CONTEXT Context;
+
+ Framework = NULL;
+ Context.MpServices.Ppi = NULL;
+ Context.CommonBuffer = NULL;
+ Context.DisabledApNumber = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
+ //
+ Status = AddCommonTestCase (Framework, &Context);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework != NULL) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
new file mode 100644
index 0000000000..ff79c5e8d4
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
@@ -0,0 +1,1776 @@
+/** @file
+ Common code to test EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "EfiMpServicesUnitTestCommom.h"
+
+/**
+ Prep routine for Unit test function.
+ To save the ProcessorNumber of disabled AP and temporarily enable it.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED Prep routine runs successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ UINTN NumberOfDisabledAPs;
+ UINTN IndexOfDisabledAPs;
+ UINTN BspNumber;
+ UINTN ProcessorNumber;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ if (LocalContext->MpServices.Ppi != NULL) {
+ return UNIT_TEST_PASSED;
+ }
+
+ Status = MpServicesUnitTestGetMpServices (&LocalContext->MpServices);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "%a: BspNumber = 0x%x\n", __FUNCTION__, BspNumber));
+
+ Status = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: NumberOfProcessors = 0x%x, NumberOfEnabledProcessors = 0x%x\n",
+ __FUNCTION__,
+ NumberOfProcessors,
+ NumberOfEnabledProcessors
+ ));
+
+ LocalContext->BspNumber = BspNumber;
+ LocalContext->NumberOfProcessors = NumberOfProcessors;
+ LocalContext->NumberOfEnabledProcessors = NumberOfEnabledProcessors;
+
+ LocalContext->CommonBuffer = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*LocalContext->CommonBuffer)));
+ UT_ASSERT_NOT_NULL (LocalContext->CommonBuffer);
+
+ NumberOfDisabledAPs = NumberOfProcessors - NumberOfEnabledProcessors;
+ if ((NumberOfDisabledAPs > 0) && (LocalContext->DisabledApNumber == NULL)) {
+ LocalContext->DisabledApNumber = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber)));
+ UT_ASSERT_NOT_NULL (LocalContext->DisabledApNumber);
+ ZeroMem (LocalContext->DisabledApNumber, NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber));
+
+ for (ProcessorNumber = 0, IndexOfDisabledAPs = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) {
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ ProcessorNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) {
+ //
+ // Save ProcessorNumber of disabled AP.
+ //
+ LocalContext->DisabledApNumber[IndexOfDisabledAPs] = ProcessorNumber;
+ IndexOfDisabledAPs++;
+
+ DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enable it.\n", __FUNCTION__, ProcessorNumber));
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ProcessorNumber,
+ TRUE,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ UT_ASSERT_TRUE (IndexOfDisabledAPs == NumberOfDisabledAPs);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Cleanup routine for Unit test function.
+ If any processor is disabled unexpectedly then reenable it.
+
+ @param[in] Context Context pointer for this test.
+**/
+VOID
+EFIAPI
+CheckUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ UINTN BspNumber;
+ UINTN ProcessorNumber;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+ ASSERT (LocalContext->MpServices.Ppi != NULL);
+
+ Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BspNumber != LocalContext->BspNumber) {
+ LocalContext->BspNumber = BspNumber;
+ DEBUG ((DEBUG_INFO, "%a: New BspNumber = 0x%x\n", __FUNCTION__, BspNumber));
+ }
+
+ ASSERT (BspNumber == LocalContext->BspNumber);
+
+ Status = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (NumberOfProcessors != LocalContext->NumberOfProcessors) {
+ LocalContext->NumberOfProcessors = NumberOfProcessors;
+ DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors = 0x%x\n", __FUNCTION__, NumberOfProcessors));
+ }
+
+ if (NumberOfEnabledProcessors != LocalContext->NumberOfProcessors) {
+ DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors = 0x%x\n", __FUNCTION__, NumberOfEnabledProcessors));
+
+ for (ProcessorNumber = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) {
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ ProcessorNumber,
+ &ProcessorInfoBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) {
+ DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and reenable it.\n", __FUNCTION__, ProcessorNumber));
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ProcessorNumber,
+ TRUE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+}
+
+/**
+ Cleanup routine for Unit test function.
+ It will be called by the last "AddTestCase" to restore AP state and free pointer.
+
+ @param[in] Context Context pointer for this test.
+**/
+VOID
+EFIAPI
+FreeUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfDisabledAPs;
+ UINTN IndexOfDisabledAPs;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ CheckUTContext (Context);
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+ ASSERT (LocalContext->MpServices.Ppi != NULL);
+
+ if (LocalContext->DisabledApNumber != NULL) {
+ NumberOfDisabledAPs = LocalContext->NumberOfProcessors - LocalContext->NumberOfEnabledProcessors;
+ for (IndexOfDisabledAPs = 0; IndexOfDisabledAPs < NumberOfDisabledAPs; IndexOfDisabledAPs++) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Disable AP(0x%x) to restore its state.\n",
+ __FUNCTION__,
+ LocalContext->DisabledApNumber[IndexOfDisabledAPs]
+ ));
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ LocalContext->DisabledApNumber[IndexOfDisabledAPs],
+ FALSE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ FreePages (LocalContext->DisabledApNumber, EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber)));
+ }
+
+ if (LocalContext->CommonBuffer != NULL) {
+ FreePages (LocalContext->CommonBuffer, EFI_SIZE_TO_PAGES (LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer)));
+ }
+}
+
+/**
+ Produce to store ProcessorNumber in the corresponding location of CommonBuffer.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+StoreCpuNumbers (
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
+ // Index 00 01 02 03 04 05
+ // Value 00 01 02 03 04 05
+ //
+ if (ProcessorNumber < LocalContext->NumberOfProcessors) {
+ LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber;
+ }
+}
+
+/**
+ Produce to store the ProcessorNumber of AP execution order in CommonBuffer.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+StoreAPsExecutionOrder (
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ UINTN *ApCounter;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
+ // Index 00 01 02 03 04 05
+ // Value 00 01 03 04 05 ApCounter(5)
+ //
+ ApCounter = &(LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1]);
+ LocalContext->CommonBuffer[*ApCounter] = ProcessorNumber;
+ (*ApCounter)++;
+}
+
+/**
+ Infinite loop procedure to be run on specified CPU.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+InfiniteLoopProcedure (
+ IN OUT VOID *Buffer
+ )
+{
+ volatile BOOLEAN InfiniteLoop;
+
+ InfiniteLoop = TRUE;
+
+ while (InfiniteLoop) {
+ }
+}
+
+/**
+ Empty procedure to be run on specified CPU.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+EmptyProcedure (
+ IN OUT VOID *Buffer
+ )
+{
+}
+
+/**
+ Procedure to run MP service GetNumberOfProcessors on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceGetNumberOfProcessorsOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+}
+
+/**
+ Procedure to run MP service GetProcessorInfo on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceGetProcessorInfoOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ LocalContext->ApNumber,
+ &ProcessorInfoBuffer
+ );
+}
+
+/**
+ Procedure to run MP service EnableDisableAP on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceEnableDisableAPOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ LocalContext->ApNumber,
+ FALSE,
+ NULL
+ );
+}
+
+/**
+ Procedure to run MP service StartupThisAP on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceStartupThisAPOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ LocalContext->ApNumber,
+ 0,
+ NULL
+ );
+}
+
+/**
+ Procedure to run MP service StartupAllAPs on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceStartupAllAPsOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ FALSE,
+ 0,
+ NULL
+ );
+}
+
+/**
+ Procedure to run MP service SwitchBSP on AP.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+RunMpServiceSwitchBSPOnAp (
+ IN OUT VOID *Buffer
+ )
+{
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
+
+ LocalContext->ApProcedureReturnStatus = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ LocalContext->ApNumber,
+ TRUE
+ );
+}
+
+/**
+ Unit test of MP service WhoAmI.
+ The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1.
+ The ProcessorNumbers of all CPUs are unique.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestWhoAmI1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ Status = MpServicesUnitTestWhoAmI (
+ LocalContext->MpServices,
+ &ProcessorNumber
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (ProcessorNumber < LocalContext->NumberOfProcessors);
+
+ SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF);
+ LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber;
+
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreCpuNumbers,
+ FALSE,
+ 0,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
+ // Index 00 01 02 03 04 05
+ // Value 00 01 02 03 04 05
+ //
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
+ UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ NumberOfProcessors should be greater that 0 and not less than NumberOfEnabledProcessors.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ Status = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (NumberOfProcessors > 0 && NumberOfProcessors >= NumberOfEnabledProcessors);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceGetNumberOfProcessorsOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ Call EnableDisableAP() to change the number of enabled AP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ FALSE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors);
+
+ if (ApNumber < LocalContext->BspNumber) {
+ UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - (ApNumber + 1));
+ } else {
+ UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - ApNumber);
+ }
+ }
+ }
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestGetNumberOfProcessors (
+ LocalContext->MpServices,
+ &NumberOfProcessors,
+ &NumberOfEnabledProcessors
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors);
+
+ if (ApNumber < LocalContext->BspNumber) {
+ UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 2);
+ } else {
+ UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 1);
+ }
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service GetProcessorInfo.
+ When all the parameters are valid, all reserved bits of StatusFlag in ProcessorInfoBuffer should be set to zero.
+ When all the parameters are valid, the StatusFlag should not have an invalid value (The BSP can never be in the disabled state.).
+ When called with nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetProcessorInfo1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ProcessorNumber = 0; ProcessorNumber <= LocalContext->NumberOfProcessors; ProcessorNumber++) {
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ ProcessorNumber,
+ &ProcessorInfoBuffer
+ );
+
+ if (ProcessorNumber == LocalContext->NumberOfProcessors) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & (UINT32) ~(PROCESSOR_AS_BSP_BIT|PROCESSOR_ENABLED_BIT|PROCESSOR_HEALTH_STATUS_BIT)) == 0);
+
+ if (ProcessorNumber == LocalContext->BspNumber) {
+ UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT));
+ } else {
+ UT_ASSERT_TRUE (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT));
+ }
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service GetProcessorInfo.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetProcessorInfo2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceGetProcessorInfoOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When called with BSP number, the return status should be EFI_INVALID_PARAMETER.
+ When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+ The AP should be really Enable/Disabled.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ FALSE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else if (ApNumber == LocalContext->NumberOfProcessors) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ ApNumber,
+ 0,
+ NULL
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ ApNumber,
+ 0,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceEnableDisableAPOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ UINT32 OldHealthFlag;
+ UINT32 NewHealthFlag;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ ApNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ OldHealthFlag = ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT;
+ NewHealthFlag = OldHealthFlag ^ PROCESSOR_HEALTH_STATUS_BIT;
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ &NewHealthFlag
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ ApNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) == NewHealthFlag);
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ &OldHealthFlag
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupThisAP.
+ When called to startup a BSP, the return status should be EFI_INVALID_PARAMETER.
+ When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+ The requested AP should execute the Procedure when called by StartupThisAP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) {
+ SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF);
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreCpuNumbers,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else if (ApNumber == LocalContext->NumberOfProcessors) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
+ UT_ASSERT_TRUE (
+ ((ProcessorIndex == ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex)) ||
+ ((ProcessorIndex != ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0))
+ );
+ }
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupThisAP.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceStartupThisAPOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupThisAP.
+ When timeout expired before the requested AP has finished, the return status should be EFI_TIMEOUT.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
+ ApNumber,
+ RUN_PROCEDURE_TIMEOUT_VALUE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupThisAP.
+ When called with disabled AP, the return status should be EFI_INVALID_PARAMETER.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP4 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ FALSE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ ApNumber,
+ 0,
+ NULL
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ ApNumber,
+ 0,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupAllAPs.
+ All APs should execute the Procedure when called by StartupAllAPs.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF);
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreCpuNumbers,
+ FALSE,
+ 0,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
+ UT_ASSERT_TRUE (
+ ((ProcessorIndex == LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) ||
+ ((ProcessorIndex != LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex))
+ );
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called in single thread, the return status should be EFI_SUCCESS and AP executes in ascending order
+ of processor handle number.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ ZeroMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer));
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreAPsExecutionOrder,
+ TRUE,
+ 0,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
+ // Index 00 01 02 03 04 05
+ // Value 00 01 03 04 05 ApCounter(5)
+ //
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors - 2; ProcessorIndex++) {
+ UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] < LocalContext->CommonBuffer[ProcessorIndex + 1]);
+ }
+
+ UT_ASSERT_EQUAL (LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1], LocalContext->NumberOfProcessors - 1);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceStartupAllAPsOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called with all AP timeout, the return status should be EFI_TIMEOUT.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs4 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
+ TRUE,
+ RUN_PROCEDURE_TIMEOUT_VALUE,
+ NULL
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
+
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
+ FALSE,
+ RUN_PROCEDURE_TIMEOUT_VALUE,
+ NULL
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called with the empty Procedure on all disabled APs, the return status should be EFI_NOT_STARTED.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs5 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ FALSE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)EmptyProcedure,
+ FALSE,
+ 0,
+ NULL
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_STARTED);
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ ApNumber,
+ TRUE,
+ NULL
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service SwitchBSP.
+ When switch current BSP to be BSP, the return status should be EFI_INVALID_PARAMETER.
+ When switch nonexistent processor to be BSP, the return status should be EFI_NOT_FOUND.
+ After switch BSP, all APs(includes new AP) should execute the Procedure when called by StartupAllAP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP1 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NewBspNumber;
+ UINTN ProcessorIndex;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (NewBspNumber = 0; NewBspNumber <= LocalContext->NumberOfProcessors; NewBspNumber++) {
+ Status = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ NewBspNumber,
+ TRUE
+ );
+
+ if (NewBspNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else if (NewBspNumber == LocalContext->NumberOfProcessors) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF);
+ Status = MpServicesUnitTestStartupAllAPs (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)StoreCpuNumbers,
+ FALSE,
+ 0,
+ (VOID *)LocalContext
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
+ UT_ASSERT_TRUE (
+ ((ProcessorIndex == NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) ||
+ ((ProcessorIndex != NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex))
+ );
+ }
+
+ Status = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ LocalContext->BspNumber,
+ TRUE
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service SwitchBSP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN ApNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
+ LocalContext->ApNumber = ApNumber;
+ Status = MpServicesUnitTestStartupThisAP (
+ LocalContext->MpServices,
+ (EFI_AP_PROCEDURE)RunMpServiceSwitchBSPOnAp,
+ ApNumber,
+ 0,
+ (VOID *)LocalContext
+ );
+
+ if (ApNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service SwitchBSP.
+ When switch a disabled AP to be BSP, the return status should be EFI_INVALID_PARAMETER.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP3 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NewBspNumber;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) {
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ NewBspNumber,
+ FALSE,
+ NULL
+ );
+
+ if (NewBspNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ NewBspNumber,
+ TRUE
+ );
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ NewBspNumber,
+ TRUE,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MP service SwitchBSP.
+ When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the enabled state and the old BSP should
+ be in the enabled state.
+ When SwitchBSP and EnableOldBSP is False, the new BSP should be in the enabled state and the old BSP should
+ be in the disabled state.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP4 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN NewBspNumber;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ MP_SERVICE_UT_CONTEXT *LocalContext;
+
+ LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
+
+ for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) {
+ Status = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ NewBspNumber,
+ FALSE
+ );
+
+ if (NewBspNumber == LocalContext->BspNumber) {
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+ } else {
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ NewBspNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (
+ (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
+ (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
+ );
+
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ LocalContext->BspNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (
+ !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
+ !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
+ );
+
+ Status = MpServicesUnitTestEnableDisableAP (
+ LocalContext->MpServices,
+ LocalContext->BspNumber,
+ TRUE,
+ NULL
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestSwitchBSP (
+ LocalContext->MpServices,
+ LocalContext->BspNumber,
+ TRUE
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ LocalContext->BspNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (
+ (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
+ (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
+ );
+
+ Status = MpServicesUnitTestGetProcessorInfo (
+ LocalContext->MpServices,
+ NewBspNumber,
+ &ProcessorInfoBuffer
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+ UT_ASSERT_TRUE (
+ !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
+ (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
+ );
+ }
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
+
+ @param[in] Framework A pointer to the framework that is being persisted.
+ @param[in] Context A pointer to the private data buffer.
+
+ @retval EFI_SUCCESS Create test suite and unit tests successfully.
+ @retval Others Create test suite and unit tests unsuccessfully.
+**/
+EFI_STATUS
+AddCommonTestCase (
+ IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
+ IN MP_SERVICE_UT_CONTEXT *Context
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_SUITE_HANDLE MpServiceWhoAmITestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceGetNumberOfProcessorsTestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceGetProcessorInfoTestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceEnableDisableAPTestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceStartupThisAPTestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceStartupAllAPsTestSuite;
+ UNIT_TEST_SUITE_HANDLE MpServiceSwitchBSPTestSuite;
+
+ MpServiceWhoAmITestSuite = NULL;
+ MpServiceGetNumberOfProcessorsTestSuite = NULL;
+ MpServiceGetProcessorInfoTestSuite = NULL;
+ MpServiceEnableDisableAPTestSuite = NULL;
+ MpServiceStartupThisAPTestSuite = NULL;
+ MpServiceStartupAllAPsTestSuite = NULL;
+ MpServiceSwitchBSPTestSuite = NULL;
+
+ //
+ // Test WhoAmI function
+ //
+ Status = CreateUnitTestSuite (&MpServiceWhoAmITestSuite, Framework, "Identify the currently executing processor", "MpServices.WhoAmI", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceWhoAmI Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceWhoAmITestSuite, "Test WhoAmI 1", "TestWhoAmI1", TestWhoAmI1, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test GetNumberOfProcessors function
+ //
+ Status = CreateUnitTestSuite (&MpServiceGetNumberOfProcessorsTestSuite, Framework, "Retrieve the number of logical processor", "MpServices.GetNumberOfProcessors", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetNumberOfProcessors Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 1", "TestGetNumberOfProcessors1", TestGetNumberOfProcessors1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 2", "TestGetNumberOfProcessors2", TestGetNumberOfProcessors2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 3", "TestGetNumberOfProcessors3", TestGetNumberOfProcessors3, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test GetProcessorInfo function
+ //
+ Status = CreateUnitTestSuite (&MpServiceGetProcessorInfoTestSuite, Framework, "Get detailed information on the requested logical processor", "MpServices.GetProcessorInfo", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetProcessorInfo Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 1", "TestGetProcessorInfo1", TestGetProcessorInfo1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 2", "TestGetProcessorInfo2", TestGetProcessorInfo2, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test EnableDisableAP function
+ //
+ Status = CreateUnitTestSuite (&MpServiceEnableDisableAPTestSuite, Framework, "Caller enables or disables an AP from this point onward", "MpServices.EnableDisableAP", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceEnableDisableAP Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 1", "TestEnableDisableAP1", TestEnableDisableAP1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 2", "TestEnableDisableAP2", TestEnableDisableAP2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 3", "TestEnableDisableAP3", TestEnableDisableAP3, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test StartupThisAP function
+ //
+ Status = CreateUnitTestSuite (&MpServiceStartupThisAPTestSuite, Framework, "Get the requested AP to execute a caller-provided function", "MpServices.StartupThisAP", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupThisAP Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 1", "TestStartupThisAP1", TestStartupThisAP1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 2", "TestStartupThisAP2", TestStartupThisAP2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 3", "TestStartupThisAP3", TestStartupThisAP3, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 4", "TestStartupThisAP4", TestStartupThisAP4, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test StartupAllAPs function
+ //
+ Status = CreateUnitTestSuite (&MpServiceStartupAllAPsTestSuite, Framework, "Execute a caller provided function on all enabled APs", "MpServices.StartupAllAPs", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupAllAPs Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 1", "TestStartupAllAPs1", TestStartupAllAPs1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 2", "TestStartupAllAPs2", TestStartupAllAPs2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 3", "TestStartupAllAPs3", TestStartupAllAPs3, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 4", "TestStartupAllAPs4", TestStartupAllAPs4, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 5", "TestStartupAllAPs5", TestStartupAllAPs5, InitUTContext, CheckUTContext, Context);
+
+ //
+ // Test SwitchBSP function
+ //
+ Status = CreateUnitTestSuite (&MpServiceSwitchBSPTestSuite, Framework, "Switch the requested AP to be the BSP from that point onward", "MpServices.SwitchBSP", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceSwitchBSP Test Suite\n"));
+ return Status;
+ }
+
+ AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 1", "TestSwitchBSP1", TestSwitchBSP1, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 2", "TestSwitchBSP2", TestSwitchBSP2, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 3", "TestSwitchBSP3", TestSwitchBSP3, InitUTContext, CheckUTContext, Context);
+ AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 4", "TestSwitchBSP4", TestSwitchBSP4, InitUTContext, FreeUTContext, Context);
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
new file mode 100644
index 0000000000..0b2ddc5585
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
@@ -0,0 +1,46 @@
+## @file
+# PEIM that unit tests the EdkiiPeiMpServices2Ppi
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EdkiiPeiMpServices2PpiPeiUnitTest
+ FILE_GUID = A4914810-4D1E-445E-BD6F-F6821B852B5D
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeiEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ EfiMpServicesUnitTestCommom.c
+ EfiMpServicesUnitTestCommom.h
+ EdkiiPeiMpServices2PpiUnitTest.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ PeimEntryPoint
+ PeiServicesLib
+ UnitTestPersistenceLib
+ UnitTestLib
+
+[Ppis]
+ gEdkiiPeiMpServices2PpiGuid ## CONSUMES
+
+[Depex]
+ gEdkiiPeiMpServices2PpiGuid
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
new file mode 100644
index 0000000000..1389092c06
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
@@ -0,0 +1,46 @@
+## @file
+# DXE driver that unit tests the EfiMpServiceProtocol
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EfiMpServiceProtocolDxeUnitTest
+ FILE_GUID = F1E468E2-A32D-4574-895D-6D82B27B08BC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ EfiMpServicesUnitTestCommom.c
+ EfiMpServicesUnitTestCommom.h
+ EfiMpServiceProtocolUnitTest.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UnitTestPersistenceLib
+ UnitTestLib
+
+[Protocols]
+ gEfiMpServiceProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiMpServiceProtocolGuid
diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h
new file mode 100644
index 0000000000..abbbd2faba
--- /dev/null
+++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h
@@ -0,0 +1,627 @@
+/** @file
+ Common header file for EfiMpServiceProtocolUnitTest DXE driver.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_
+#define EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_
+
+#include <PiPei.h>
+#include <Ppi/MpServices2.h>
+#include <Protocol/MpService.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+
+#define RUN_PROCEDURE_TIMEOUT_VALUE 100000 // microseconds
+
+typedef union {
+ EDKII_PEI_MP_SERVICES2_PPI *Ppi;
+ EFI_MP_SERVICES_PROTOCOL *Protocol;
+} MP_SERVICES;
+
+typedef struct {
+ MP_SERVICES MpServices;
+ UINTN BspNumber;
+ UINTN ApNumber;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
+ UINTN *CommonBuffer;
+ EFI_STATUS ApProcedureReturnStatus;
+ UINTN *DisabledApNumber;
+} MP_SERVICE_UT_CONTEXT;
+
+/**
+ Get EFI_MP_SERVICES_PROTOCOL pointer.
+
+ @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored
+
+ @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned
+ @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found
+**/
+EFI_STATUS
+MpServicesUnitTestGetMpServices (
+ OUT MP_SERVICES *MpServices
+ );
+
+/**
+ Retrieve the number of logical processor in the platform and the number of those logical processors that
+ are enabled on this boot.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
+ the BSP and disabled APs.
+ @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
+
+ @retval EFI_SUCCESS Retrieve the number of logical processor successfully
+ @retval Others Retrieve the number of logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetNumberOfProcessors (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ );
+
+/**
+ Get detailed information on the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the processor.
+ @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
+
+ @retval EFI_SUCCESS Get information on the requested logical processor successfully
+ @retval Others Get information on the requested logical processor unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ Execute a caller provided function on all enabled APs.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
+ one by one, in ascending order of processor handle number.
+ If FALSE, then all the enabled APs execute the function specified by Procedure
+ simultaneously.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+ @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
+ @retval Others Execute a caller provided function on all enabled APs unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupAllAPs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ );
+
+/**
+ Caller gets one enabled AP to execute a caller-provided function.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
+ for blocking mode only. Zero means infinity.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
+
+ @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
+ @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestStartupThisAP (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument
+ );
+
+/**
+ Switch the requested AP to be the BSP from that point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
+ @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
+
+ @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
+ @retval Others Switch the requested AP to be the BSP unsuccessfully
+**/
+EFI_STATUS
+MpServicesUnitTestSwitchBSP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ );
+
+/**
+ Caller enables or disables an AP from this point onward.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
+ @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
+
+ @retval EFI_SUCCESS Caller enables or disables an AP successfully.
+ @retval Others Caller enables or disables an AP unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestEnableDisableAP (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag
+ );
+
+/**
+ Get the handle number for the calling processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[out] ProcessorNumber The handle number for the calling processor.
+
+ @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
+ @retval Others Get the handle number for the calling processor unsuccessfully.
+**/
+EFI_STATUS
+MpServicesUnitTestWhoAmI (
+ IN MP_SERVICES MpServices,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Empty procedure to be run on specified CPU.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+EmptyProcedure (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Produce to store ProcessorNumber in CommonBuffer and be run on specified CPU.
+
+ @param[in,out] Buffer The pointer to private data buffer.
+**/
+VOID
+StoreCpuNumbers (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Prep routine for Unit test function.
+ To save the ProcessorNumber of disabled AP and temporarily enable it.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED Prep routine runs successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Cleanup routine for Unit test function.
+ If any processor is disabled unexpectedly then reenable it.
+
+ @param[in] Context Context pointer for this test.
+**/
+VOID
+EFIAPI
+CheckUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Cleanup routine for Unit test function.
+ It will be called by the last "AddTestCase" to restore AP state and free pointer.
+
+ @param[in] Context Context pointer for this test.
+**/
+VOID
+EFIAPI
+FreeUTContext (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service WhoAmI.
+ The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1.
+ The ProcessorNumbers of all CPUs are unique.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestWhoAmI1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ NumberOfProcessors should be greater that 0 and not less than NumberOfEnabledProcessors.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service GetNumberOfProcessors.
+ Call EnableDisableAP() to change the number of enabled AP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetNumberOfProcessors3 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service GetProcessorInfo.
+ When all the parameters are valid, all reserved bits of StatusFlag in ProcessorInfoBuffer should be set to zero.
+ When all the parameters are valid, the StatusFlag should not have an invalid value (The BSP can never be in the disabled state.).
+ When called with nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetProcessorInfo1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service GetProcessorInfo.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestGetProcessorInfo2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When called with BSP number, the return status should be EFI_INVALID_PARAMETER.
+ When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+ The AP should be really Enable/Disabled.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service EnableDisableAP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestEnableDisableAP3 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupThisAP.
+ When called to startup a BSP, the return status should be EFI_INVALID_PARAMETER.
+ When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
+ The requested AP should execute the Procedure when called by StartupThisAP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupThisAP.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupThisAP.
+ When timeout expired before the requested AP has finished, the return status should be EFI_TIMEOUT.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP3 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupThisAP.
+ When called with disabled AP, the return status should be EFI_INVALID_PARAMETER.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupThisAP4 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupAllAPs.
+ All APs should execute the Procedure when called by StartupAllAPs.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called in single thread, the return status should be EFI_SUCCESS and AP executes in ascending order
+ of processor handle number.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs3 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called with all AP timeout, the return status should be EFI_TIMEOUT.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs4 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service StartupAllAPs.
+ When called with the empty Procedure on all disabled APs, the return status should be EFI_NOT_STARTED.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestStartupAllAPs5 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service SwitchBSP.
+ When switch current BSP to be BSP, the return status should be EFI_INVALID_PARAMETER.
+ When switch nonexistent processor to be BSP, the return status should be EFI_NOT_FOUND.
+ After switch BSP, all APs(includes new AP) should execute the Procedure when called by StartupAllAP.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP1 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service SwitchBSP.
+ When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP2 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service SwitchBSP.
+ When switch a disabled AP to be BSP, the return status should be EFI_INVALID_PARAMETER.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP3 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Unit test of MP service SwitchBSP.
+ When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the enabled state and the old BSP should
+ be in the enabled state.
+ When SwitchBSP and EnableOldBSP is False, the new BSP should be in the enabled state and the old BSP should
+ be in the disabled state.
+
+ @param[in] Context Context pointer for this test.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestSwitchBSP4 (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
+
+ @param[in] Framework A pointer to the framework that is being persisted.
+ @param[in] Context A pointer to the private data buffer.
+
+ @retval EFI_SUCCESS Create test suite and unit tests successfully.
+ @retval Others Create test suite and unit tests unsuccessfully.
+**/
+EFI_STATUS
+AddCommonTestCase (
+ IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
+ IN MP_SERVICE_UT_CONTEXT *Context
+ );
+
+#endif
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index f694b3a77c..db5fe654b5 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -63,6 +63,9 @@
MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
+ UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf
+ UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
+ UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf
[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -177,6 +180,8 @@
UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
+ UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
+ UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
--
2.28.0.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol
2022-10-10 13:52 [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol Jason Lou
@ 2022-10-14 6:18 ` Ni, Ray
0 siblings, 0 replies; 2+ messages in thread
From: Ni, Ray @ 2022-10-14 6:18 UTC (permalink / raw)
To: Lou, Yun, devel@edk2.groups.io; +Cc: Dong, Eric, Laszlo Ersek, Kumar, Rahul R
Reviewed-by: Ray Ni <ray.ni@intel.com>
> -----Original Message-----
> From: Lou, Yun <yun.lou@intel.com>
> Sent: Monday, October 10, 2022 9:53 PM
> To: devel@edk2.groups.io
> Cc: Lou, Yun <yun.lou@intel.com>; Ni, Ray <ray.ni@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo Ersek
> <lersek@redhat.com>; Kumar, Rahul R <rahul.r.kumar@intel.com>
> Subject: [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol
>
> From: Jason Lou <yun.lou@intel.com>
>
> The code changes add unit tests based on current UnitTestFramework.
> EdkiiPeiMpServices2PpiPeiUnitTest PEI module is used to test
> EdkiiPeiMpServices2Ppi and EfiMpServiceProtocolDxeUnitTest DXE driver is
> used to test EfiMpServiceProtocol.
>
> Signed-off-by: Jason Lou <yun.lou@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> ---
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c | 477 ++++++
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c | 244 +++
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c | 1776
> ++++++++++++++++++++
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf | 46 +
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf | 46 +
> UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h | 627 +++++++
> UefiCpuPkg/UefiCpuPkg.dsc | 5 +
> 7 files changed, 3221 insertions(+)
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c
> new file mode 100644
> index 0000000000..5c42a81d29
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c
> @@ -0,0 +1,477 @@
> +/** @file
>
> + PEI Module to test APIs defined in EdkiiPeiMpServices2Ppi.
>
> +
>
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/PeimEntryPoint.h>
>
> +#include <Library/PeiServicesLib.h>
>
> +#include "EfiMpServicesUnitTestCommom.h"
>
> +
>
> +#define UNIT_TEST_NAME "EdkiiPeiMpServices2Ppi Unit Test"
>
> +#define UNIT_TEST_VERSION "0.1"
>
> +
>
> +/**
>
> + Get EDKII_PEI_MP_SERVICES2_PPI pointer.
>
> +
>
> + @param[out] MpServices Pointer to the buffer where EDKII_PEI_MP_SERVICES2_PPI is stored.
>
> +
>
> + @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is returned
>
> + @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not found
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetMpServices (
>
> + OUT MP_SERVICES *MpServices
>
> + )
>
> +{
>
> + return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOID **)&MpServices->Ppi);
>
> +}
>
> +
>
> +/**
>
> + Retrieve the number of logical processor in the platform and the number of those logical processors that
>
> + are enabled on this boot.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
>
> + the BSP and disabled APs.
>
> + @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
>
> +
>
> + @retval EFI_SUCCESS Retrieve the number of logical processor successfully
>
> + @retval Others Retrieve the number of logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetNumberOfProcessors (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *NumberOfProcessors,
>
> + OUT UINTN *NumberOfEnabledProcessors
>
> + )
>
> +{
>
> + return MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, NumberOfProcessors,
> NumberOfEnabledProcessors);
>
> +}
>
> +
>
> +/**
>
> + Get detailed information on the requested logical processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the processor.
>
> + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
>
> +
>
> + @retval EFI_SUCCESS Get information on the requested logical processor successfully
>
> + @retval Others Get information on the requested logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetProcessorInfo (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
>
> + )
>
> +{
>
> + return MpServices.Ppi->GetProcessorInfo (MpServices.Ppi, ProcessorNumber, ProcessorInfoBuffer);
>
> +}
>
> +
>
> +/**
>
> + Execute a caller provided function on all enabled APs.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
>
> + one by one, in ascending order of processor handle number.
>
> + If FALSE, then all the enabled APs execute the function specified by Procedure
>
> + simultaneously.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> + @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
>
> + @retval Others Execute a caller provided function on all enabled APs unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupAllAPs (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN BOOLEAN SingleThread,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + )
>
> +{
>
> + return MpServices.Ppi->StartupAllAPs (MpServices.Ppi, Procedure, SingleThread, TimeoutInMicroSeconds,
> ProcedureArgument);
>
> +}
>
> +
>
> +/**
>
> + Caller gets one enabled AP to execute a caller-provided function.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> +
>
> + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
>
> + @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupThisAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN UINTN ProcessorNumber,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + )
>
> +{
>
> + return MpServices.Ppi->StartupThisAP (MpServices.Ppi, Procedure, ProcessorNumber, TimeoutInMicroSeconds,
> ProcedureArgument);
>
> +}
>
> +
>
> +/**
>
> + Switch the requested AP to be the BSP from that point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
>
> + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
>
> +
>
> + @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
>
> + @retval Others Switch the requested AP to be the BSP unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestSwitchBSP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableOldBSP
>
> + )
>
> +{
>
> + return MpServices.Ppi->SwitchBSP (MpServices.Ppi, ProcessorNumber, EnableOldBSP);
>
> +}
>
> +
>
> +/**
>
> + Caller enables or disables an AP from this point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
>
> + @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
>
> +
>
> + @retval EFI_SUCCESS Caller enables or disables an AP successfully.
>
> + @retval Others Caller enables or disables an AP unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestEnableDisableAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableAP,
>
> + IN UINT32 *HealthFlag
>
> + )
>
> +{
>
> + return MpServices.Ppi->EnableDisableAP (MpServices.Ppi, ProcessorNumber, EnableAP, HealthFlag);
>
> +}
>
> +
>
> +/**
>
> + Get the handle number for the calling processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] ProcessorNumber The handle number for the calling processor.
>
> +
>
> + @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
>
> + @retval Others Get the handle number for the calling processor unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestWhoAmI (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *ProcessorNumber
>
> + )
>
> +{
>
> + return MpServices.Ppi->WhoAmI (MpServices.Ppi, ProcessorNumber);
>
> +}
>
> +
>
> +/**
>
> + Execute a caller provided function on all enabled CPUs.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled CPUs of the system.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all enabled CPUs.
>
> +
>
> + @retval EFI_SUCCESS Execute a caller provided function on all enabled CPUs successfully
>
> + @retval Others Execute a caller provided function on all enabled CPUs unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupAllCPUs (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + )
>
> +{
>
> + return MpServices.Ppi->StartupAllCPUs (MpServices.Ppi, Procedure, TimeoutInMicroSeconds, ProcedureArgument);
>
> +}
>
> +
>
> +/**
>
> + Infinite loop procedure to be run on specified AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +ApInfiniteLoopProcedure (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorNumber;
>
> + volatile BOOLEAN InfiniteLoop;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (ProcessorNumber == LocalContext->BspNumber) {
>
> + InfiniteLoop = FALSE;
>
> + } else {
>
> + InfiniteLoop = TRUE;
>
> + }
>
> +
>
> + while (InfiniteLoop) {
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service StartupAllCPUs on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceStartupAllCPUsOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupAllCPUs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + 0,
>
> + NULL
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Unit test of PEI MP service StartupAllCPU.
>
> + All CPUs should execute the Procedure.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllCPUs1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer), 0xFF);
>
> + Status = MpServicesUnitTestStartupAllCPUs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreCpuNumbers,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex);
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of PEI MP service StartupAllCPU.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllCPUs2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceStartupAllCPUsOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of PEI MP service StartupAllCPU.
>
> + When called with all CPUs timeout, the return status should be EFI_TIMEOUT.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllCPUs3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + Status = MpServicesUnitTestStartupAllCPUs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)ApInfiniteLoopProcedure,
>
> + RUN_PROCEDURE_TIMEOUT_VALUE,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Create test suite and unit tests only for EdkiiPeiMpServices2Ppi.
>
> +
>
> + @param[in] Framework A pointer to the framework that is being persisted.
>
> + @param[in] Context A pointer to the private data buffer.
>
> +
>
> + @retval EFI_SUCCESS Create test suite and unit tests successfully.
>
> + @retval Others Create test suite and unit tests unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +AddTestCaseOnlyForEdkiiPeiMpServices2Ppi (
>
> + IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
>
> + IN MP_SERVICE_UT_CONTEXT *Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceStartupAllCPUsTestSuite;
>
> +
>
> + MpServiceStartupAllCPUsTestSuite = NULL;
>
> +
>
> + //
>
> + // Test StartupAllCPUs function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceStartupAllCPUsTestSuite, Framework, "Execute a caller provided function on
> all enabled CPUs", "MpServices.StartupAllCPUs", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupAllCPUs Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 1", "TestStartupAllCPUs1", TestStartupAllCPUs1,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 2", "TestStartupAllCPUs2", TestStartupAllCPUs2,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 3", "TestStartupAllCPUs3", TestStartupAllCPUs3,
> InitUTContext, CheckUTContext, Context);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Standard PEIM entry point for unit test execution from PEI.
>
> + Initialize the unit test framework, suite, and unit tests for the EdkiiPeiMpServices2Ppi and run the unit test.
>
> +
>
> + @param[in] FileHandle Handle of the file being invoked.
>
> + @param[in] PeiServices Pointer to PEI Services table.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +PeiEntryPoint (
>
> + IN EFI_PEI_FILE_HANDLE FileHandle,
>
> + IN CONST EFI_PEI_SERVICES **PeiServices
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UNIT_TEST_FRAMEWORK_HANDLE Framework;
>
> + MP_SERVICE_UT_CONTEXT Context;
>
> +
>
> + Framework = NULL;
>
> + Context.MpServices.Ppi = NULL;
>
> + Context.CommonBuffer = NULL;
>
> + Context.DisabledApNumber = NULL;
>
> +
>
> + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
>
> +
>
> + //
>
> + // Start setting up the test framework for running the tests.
>
> + //
>
> + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
>
> + goto EXIT;
>
> + }
>
> +
>
> + //
>
> + // Create test suite and unit tests only for EdkiiPeiMpServices2Ppi.
>
> + //
>
> + Status = AddTestCaseOnlyForEdkiiPeiMpServices2Ppi (Framework, &Context);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in AddTestCaseOnlyForEdkiiPeiMpServices2Ppi. Status = %r\n", Status));
>
> + goto EXIT;
>
> + }
>
> +
>
> + //
>
> + // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
>
> + //
>
> + Status = AddCommonTestCase (Framework, &Context);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));
>
> + goto EXIT;
>
> + }
>
> +
>
> + //
>
> + // Execute the tests.
>
> + //
>
> + Status = RunAllTestSuites (Framework);
>
> +
>
> +EXIT:
>
> + if (Framework != NULL) {
>
> + FreeUnitTestFramework (Framework);
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c
> new file mode 100644
> index 0000000000..57f8ba3c06
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c
> @@ -0,0 +1,244 @@
> +/** @file
>
> + PEI Module to test EfiMpServiceProtocol.
>
> +
>
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <PiDxe.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include "EfiMpServicesUnitTestCommom.h"
>
> +
>
> +#define UNIT_TEST_NAME "EfiMpServiceProtocol Unit Test"
>
> +#define UNIT_TEST_VERSION "0.1"
>
> +
>
> +/**
>
> + Get EFI_MP_SERVICES_PROTOCOL pointer.
>
> +
>
> + @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored
>
> +
>
> + @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned
>
> + @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetMpServices (
>
> + OUT MP_SERVICES *MpServices
>
> + )
>
> +{
>
> + return gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices->Protocol);
>
> +}
>
> +
>
> +/**
>
> + Retrieve the number of logical processor in the platform and the number of those logical processors that
>
> + are enabled on this boot.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
>
> + the BSP and disabled APs.
>
> + @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
>
> +
>
> + @retval EFI_SUCCESS Retrieve the number of logical processor successfully
>
> + @retval Others Retrieve the number of logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetNumberOfProcessors (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *NumberOfProcessors,
>
> + OUT UINTN *NumberOfEnabledProcessors
>
> + )
>
> +{
>
> + return MpServices.Protocol->GetNumberOfProcessors (MpServices.Protocol, NumberOfProcessors,
> NumberOfEnabledProcessors);
>
> +}
>
> +
>
> +/**
>
> + Get detailed information on the requested logical processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the processor.
>
> + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
>
> +
>
> + @retval EFI_SUCCESS Get information on the requested logical processor successfully
>
> + @retval Others Get information on the requested logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetProcessorInfo (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
>
> + )
>
> +{
>
> + return MpServices.Protocol->GetProcessorInfo (MpServices.Protocol, ProcessorNumber, ProcessorInfoBuffer);
>
> +}
>
> +
>
> +/**
>
> + Execute a caller provided function on all enabled APs.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
>
> + one by one, in ascending order of processor handle number.
>
> + If FALSE, then all the enabled APs execute the function specified by Procedure
>
> + simultaneously.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> + @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
>
> + @retval Others Execute a caller provided function on all enabled APs unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupAllAPs (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN BOOLEAN SingleThread,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + )
>
> +{
>
> + return MpServices.Protocol->StartupAllAPs (MpServices.Protocol, Procedure, SingleThread, NULL,
> TimeoutInMicroSeconds, ProcedureArgument, NULL);
>
> +}
>
> +
>
> +/**
>
> + Caller gets one enabled AP to execute a caller-provided function.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> +
>
> + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
>
> + @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupThisAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN UINTN ProcessorNumber,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + )
>
> +{
>
> + return MpServices.Protocol->StartupThisAP (MpServices.Protocol, Procedure, ProcessorNumber, NULL,
> TimeoutInMicroSeconds, ProcedureArgument, NULL);
>
> +}
>
> +
>
> +/**
>
> + Switch the requested AP to be the BSP from that point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
>
> + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
>
> +
>
> + @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
>
> + @retval Others Switch the requested AP to be the BSP unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestSwitchBSP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableOldBSP
>
> + )
>
> +{
>
> + return MpServices.Protocol->SwitchBSP (MpServices.Protocol, ProcessorNumber, EnableOldBSP);
>
> +}
>
> +
>
> +/**
>
> + Caller enables or disables an AP from this point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
>
> + @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
>
> +
>
> + @retval EFI_SUCCESS Caller enables or disables an AP successfully.
>
> + @retval Others Caller enables or disables an AP unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestEnableDisableAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableAP,
>
> + IN UINT32 *HealthFlag
>
> + )
>
> +{
>
> + return MpServices.Protocol->EnableDisableAP (MpServices.Protocol, ProcessorNumber, EnableAP, HealthFlag);
>
> +}
>
> +
>
> +/**
>
> + Get the handle number for the calling processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] ProcessorNumber The handle number for the calling processor.
>
> +
>
> + @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
>
> + @retval Others Get the handle number for the calling processor unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestWhoAmI (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *ProcessorNumber
>
> + )
>
> +{
>
> + return MpServices.Protocol->WhoAmI (MpServices.Protocol, ProcessorNumber);
>
> +}
>
> +
>
> +/**
>
> + Standard DXE driver or UEFI application entry point for unit test execution from DXE or UEFI Shell.
>
> + Initialize the unit test framework, suite, and unit tests for the EfiMpServiceProtocol and run the unit test.
>
> +
>
> + @param[in] ImageHandle The firmware allocated handle for the EFI image.
>
> + @param[in] SystemTable A pointer to the EFI System Table.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DxeEntryPoint (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UNIT_TEST_FRAMEWORK_HANDLE Framework;
>
> + MP_SERVICE_UT_CONTEXT Context;
>
> +
>
> + Framework = NULL;
>
> + Context.MpServices.Ppi = NULL;
>
> + Context.CommonBuffer = NULL;
>
> + Context.DisabledApNumber = NULL;
>
> +
>
> + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
>
> +
>
> + //
>
> + // Start setting up the test framework for running the tests.
>
> + //
>
> + Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
>
> + goto EXIT;
>
> + }
>
> +
>
> + //
>
> + // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
>
> + //
>
> + Status = AddCommonTestCase (Framework, &Context);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status = %r\n", Status));
>
> + goto EXIT;
>
> + }
>
> +
>
> + //
>
> + // Execute the tests.
>
> + //
>
> + Status = RunAllTestSuites (Framework);
>
> +
>
> +EXIT:
>
> + if (Framework != NULL) {
>
> + FreeUnitTestFramework (Framework);
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
> new file mode 100644
> index 0000000000..ff79c5e8d4
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
> @@ -0,0 +1,1776 @@
> +/** @file
>
> + Common code to test EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
>
> +
>
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include "EfiMpServicesUnitTestCommom.h"
>
> +
>
> +/**
>
> + Prep routine for Unit test function.
>
> + To save the ProcessorNumber of disabled AP and temporarily enable it.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED Prep routine runs successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + UINTN NumberOfDisabledAPs;
>
> + UINTN IndexOfDisabledAPs;
>
> + UINTN BspNumber;
>
> + UINTN ProcessorNumber;
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + if (LocalContext->MpServices.Ppi != NULL) {
>
> + return UNIT_TEST_PASSED;
>
> + }
>
> +
>
> + Status = MpServicesUnitTestGetMpServices (&LocalContext->MpServices);
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber);
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + DEBUG ((DEBUG_INFO, "%a: BspNumber = 0x%x\n", __FUNCTION__, BspNumber));
>
> +
>
> + Status = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + DEBUG ((
>
> + DEBUG_INFO,
>
> + "%a: NumberOfProcessors = 0x%x, NumberOfEnabledProcessors = 0x%x\n",
>
> + __FUNCTION__,
>
> + NumberOfProcessors,
>
> + NumberOfEnabledProcessors
>
> + ));
>
> +
>
> + LocalContext->BspNumber = BspNumber;
>
> + LocalContext->NumberOfProcessors = NumberOfProcessors;
>
> + LocalContext->NumberOfEnabledProcessors = NumberOfEnabledProcessors;
>
> +
>
> + LocalContext->CommonBuffer = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer)));
>
> + UT_ASSERT_NOT_NULL (LocalContext->CommonBuffer);
>
> +
>
> + NumberOfDisabledAPs = NumberOfProcessors - NumberOfEnabledProcessors;
>
> + if ((NumberOfDisabledAPs > 0) && (LocalContext->DisabledApNumber == NULL)) {
>
> + LocalContext->DisabledApNumber = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof
> (*LocalContext->DisabledApNumber)));
>
> + UT_ASSERT_NOT_NULL (LocalContext->DisabledApNumber);
>
> + ZeroMem (LocalContext->DisabledApNumber, NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber));
>
> +
>
> + for (ProcessorNumber = 0, IndexOfDisabledAPs = 0; ProcessorNumber < LocalContext->NumberOfProcessors;
> ProcessorNumber++) {
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + ProcessorNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) {
>
> + //
>
> + // Save ProcessorNumber of disabled AP.
>
> + //
>
> + LocalContext->DisabledApNumber[IndexOfDisabledAPs] = ProcessorNumber;
>
> + IndexOfDisabledAPs++;
>
> +
>
> + DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enable it.\n", __FUNCTION__, ProcessorNumber));
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ProcessorNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + UT_ASSERT_TRUE (IndexOfDisabledAPs == NumberOfDisabledAPs);
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Cleanup routine for Unit test function.
>
> + If any processor is disabled unexpectedly then reenable it.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +CheckUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + UINTN BspNumber;
>
> + UINTN ProcessorNumber;
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> + ASSERT (LocalContext->MpServices.Ppi != NULL);
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (BspNumber != LocalContext->BspNumber) {
>
> + LocalContext->BspNumber = BspNumber;
>
> + DEBUG ((DEBUG_INFO, "%a: New BspNumber = 0x%x\n", __FUNCTION__, BspNumber));
>
> + }
>
> +
>
> + ASSERT (BspNumber == LocalContext->BspNumber);
>
> +
>
> + Status = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (NumberOfProcessors != LocalContext->NumberOfProcessors) {
>
> + LocalContext->NumberOfProcessors = NumberOfProcessors;
>
> + DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors = 0x%x\n", __FUNCTION__, NumberOfProcessors));
>
> + }
>
> +
>
> + if (NumberOfEnabledProcessors != LocalContext->NumberOfProcessors) {
>
> + DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors = 0x%x\n", __FUNCTION__,
> NumberOfEnabledProcessors));
>
> +
>
> + for (ProcessorNumber = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) {
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + ProcessorNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) {
>
> + DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and reenable it.\n", __FUNCTION__,
> ProcessorNumber));
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ProcessorNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Cleanup routine for Unit test function.
>
> + It will be called by the last "AddTestCase" to restore AP state and free pointer.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +FreeUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NumberOfDisabledAPs;
>
> + UINTN IndexOfDisabledAPs;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + CheckUTContext (Context);
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> + ASSERT (LocalContext->MpServices.Ppi != NULL);
>
> +
>
> + if (LocalContext->DisabledApNumber != NULL) {
>
> + NumberOfDisabledAPs = LocalContext->NumberOfProcessors - LocalContext->NumberOfEnabledProcessors;
>
> + for (IndexOfDisabledAPs = 0; IndexOfDisabledAPs < NumberOfDisabledAPs; IndexOfDisabledAPs++) {
>
> + DEBUG ((
>
> + DEBUG_INFO,
>
> + "%a: Disable AP(0x%x) to restore its state.\n",
>
> + __FUNCTION__,
>
> + LocalContext->DisabledApNumber[IndexOfDisabledAPs]
>
> + ));
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + LocalContext->DisabledApNumber[IndexOfDisabledAPs],
>
> + FALSE,
>
> + NULL
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> +
>
> + FreePages (LocalContext->DisabledApNumber, EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof (*LocalContext-
> >DisabledApNumber)));
>
> + }
>
> +
>
> + if (LocalContext->CommonBuffer != NULL) {
>
> + FreePages (LocalContext->CommonBuffer, EFI_SIZE_TO_PAGES (LocalContext->NumberOfProcessors * sizeof
> (*LocalContext->CommonBuffer)));
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Produce to store ProcessorNumber in the corresponding location of CommonBuffer.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +StoreCpuNumbers (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + //
>
> + // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
>
> + // Index 00 01 02 03 04 05
>
> + // Value 00 01 02 03 04 05
>
> + //
>
> + if (ProcessorNumber < LocalContext->NumberOfProcessors) {
>
> + LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Produce to store the ProcessorNumber of AP execution order in CommonBuffer.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +StoreAPsExecutionOrder (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorNumber;
>
> + UINTN *ApCounter;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + //
>
> + // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
>
> + // Index 00 01 02 03 04 05
>
> + // Value 00 01 03 04 05 ApCounter(5)
>
> + //
>
> + ApCounter = &(LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1]);
>
> + LocalContext->CommonBuffer[*ApCounter] = ProcessorNumber;
>
> + (*ApCounter)++;
>
> +}
>
> +
>
> +/**
>
> + Infinite loop procedure to be run on specified CPU.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +InfiniteLoopProcedure (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + volatile BOOLEAN InfiniteLoop;
>
> +
>
> + InfiniteLoop = TRUE;
>
> +
>
> + while (InfiniteLoop) {
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Empty procedure to be run on specified CPU.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +EmptyProcedure (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service GetNumberOfProcessors on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceGetNumberOfProcessorsOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service GetProcessorInfo on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceGetProcessorInfoOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + LocalContext->ApNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service EnableDisableAP on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceEnableDisableAPOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + LocalContext->ApNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service StartupThisAP on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceStartupThisAPOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + LocalContext->ApNumber,
>
> + 0,
>
> + NULL
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service StartupAllAPs on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceStartupAllAPsOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + FALSE,
>
> + 0,
>
> + NULL
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Procedure to run MP service SwitchBSP on AP.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +RunMpServiceSwitchBSPOnAp (
>
> + IN OUT VOID *Buffer
>
> + )
>
> +{
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer;
>
> +
>
> + LocalContext->ApProcedureReturnStatus = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + LocalContext->ApNumber,
>
> + TRUE
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service WhoAmI.
>
> + The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1.
>
> + The ProcessorNumbers of all CPUs are unique.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestWhoAmI1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorNumber;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + Status = MpServicesUnitTestWhoAmI (
>
> + LocalContext->MpServices,
>
> + &ProcessorNumber
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (ProcessorNumber < LocalContext->NumberOfProcessors);
>
> +
>
> + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer), 0xFF);
>
> + LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber;
>
> +
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreCpuNumbers,
>
> + FALSE,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + //
>
> + // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
>
> + // Index 00 01 02 03 04 05
>
> + // Value 00 01 02 03 04 05
>
> + //
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex);
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + NumberOfProcessors should be greater that 0 and not less than NumberOfEnabledProcessors.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + Status = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (NumberOfProcessors > 0 && NumberOfProcessors >= NumberOfEnabledProcessors);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceGetNumberOfProcessorsOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + Call EnableDisableAP() to change the number of enabled AP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors);
>
> +
>
> + if (ApNumber < LocalContext->BspNumber) {
>
> + UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - (ApNumber + 1));
>
> + } else {
>
> + UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - ApNumber);
>
> + }
>
> + }
>
> + }
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestGetNumberOfProcessors (
>
> + LocalContext->MpServices,
>
> + &NumberOfProcessors,
>
> + &NumberOfEnabledProcessors
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors);
>
> +
>
> + if (ApNumber < LocalContext->BspNumber) {
>
> + UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 2);
>
> + } else {
>
> + UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 1);
>
> + }
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service GetProcessorInfo.
>
> + When all the parameters are valid, all reserved bits of StatusFlag in ProcessorInfoBuffer should be set to zero.
>
> + When all the parameters are valid, the StatusFlag should not have an invalid value (The BSP can never be in the disabled
> state.).
>
> + When called with nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetProcessorInfo1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorNumber;
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ProcessorNumber = 0; ProcessorNumber <= LocalContext->NumberOfProcessors; ProcessorNumber++) {
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + ProcessorNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> +
>
> + if (ProcessorNumber == LocalContext->NumberOfProcessors) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & (UINT32)
> ~(PROCESSOR_AS_BSP_BIT|PROCESSOR_ENABLED_BIT|PROCESSOR_HEALTH_STATUS_BIT)) == 0);
>
> +
>
> + if (ProcessorNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag
> & PROCESSOR_ENABLED_BIT));
>
> + } else {
>
> + UT_ASSERT_TRUE (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT));
>
> + }
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service GetProcessorInfo.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetProcessorInfo2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceGetProcessorInfoOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When called with BSP number, the return status should be EFI_INVALID_PARAMETER.
>
> + When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> + The AP should be really Enable/Disabled.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else if (ApNumber == LocalContext->NumberOfProcessors) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + ApNumber,
>
> + 0,
>
> + NULL
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + ApNumber,
>
> + 0,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceEnableDisableAPOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + UINT32 OldHealthFlag;
>
> + UINT32 NewHealthFlag;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + OldHealthFlag = ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT;
>
> + NewHealthFlag = OldHealthFlag ^ PROCESSOR_HEALTH_STATUS_BIT;
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + &NewHealthFlag
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) == NewHealthFlag);
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + &OldHealthFlag
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When called to startup a BSP, the return status should be EFI_INVALID_PARAMETER.
>
> + When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> + The requested AP should execute the Procedure when called by StartupThisAP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) {
>
> + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer), 0xFF);
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreCpuNumbers,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else if (ApNumber == LocalContext->NumberOfProcessors) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (
>
> + ((ProcessorIndex == ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex)) ||
>
> + ((ProcessorIndex != ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0))
>
> + );
>
> + }
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceStartupThisAPOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When timeout expired before the requested AP has finished, the return status should be EFI_TIMEOUT.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
>
> + ApNumber,
>
> + RUN_PROCEDURE_TIMEOUT_VALUE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When called with disabled AP, the return status should be EFI_INVALID_PARAMETER.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + ApNumber,
>
> + 0,
>
> + NULL
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + ApNumber,
>
> + 0,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + All APs should execute the Procedure when called by StartupAllAPs.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer), 0xFF);
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreCpuNumbers,
>
> + FALSE,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (
>
> + ((ProcessorIndex == LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0))
> ||
>
> + ((ProcessorIndex != LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] ==
> ProcessorIndex))
>
> + );
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called in single thread, the return status should be EFI_SUCCESS and AP executes in ascending order
>
> + of processor handle number.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + ZeroMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer));
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreAPsExecutionOrder,
>
> + TRUE,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + //
>
> + // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6)
>
> + // Index 00 01 02 03 04 05
>
> + // Value 00 01 03 04 05 ApCounter(5)
>
> + //
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors - 2; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] < LocalContext->CommonBuffer[ProcessorIndex +
> 1]);
>
> + }
>
> +
>
> + UT_ASSERT_EQUAL (LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1], LocalContext-
> >NumberOfProcessors - 1);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceStartupAllAPsOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called with all AP timeout, the return status should be EFI_TIMEOUT.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
>
> + TRUE,
>
> + RUN_PROCEDURE_TIMEOUT_VALUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
>
> +
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)InfiniteLoopProcedure,
>
> + FALSE,
>
> + RUN_PROCEDURE_TIMEOUT_VALUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called with the empty Procedure on all disabled APs, the return status should be EFI_NOT_STARTED.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs5 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)EmptyProcedure,
>
> + FALSE,
>
> + 0,
>
> + NULL
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_STARTED);
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + ApNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When switch current BSP to be BSP, the return status should be EFI_INVALID_PARAMETER.
>
> + When switch nonexistent processor to be BSP, the return status should be EFI_NOT_FOUND.
>
> + After switch BSP, all APs(includes new AP) should execute the Procedure when called by StartupAllAP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NewBspNumber;
>
> + UINTN ProcessorIndex;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (NewBspNumber = 0; NewBspNumber <= LocalContext->NumberOfProcessors; NewBspNumber++) {
>
> + Status = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + TRUE
>
> + );
>
> +
>
> + if (NewBspNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else if (NewBspNumber == LocalContext->NumberOfProcessors) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext-
> >CommonBuffer), 0xFF);
>
> + Status = MpServicesUnitTestStartupAllAPs (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)StoreCpuNumbers,
>
> + FALSE,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) {
>
> + UT_ASSERT_TRUE (
>
> + ((ProcessorIndex == NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) ||
>
> + ((ProcessorIndex != NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex))
>
> + );
>
> + }
>
> +
>
> + Status = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + LocalContext->BspNumber,
>
> + TRUE
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN ApNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) {
>
> + LocalContext->ApNumber = ApNumber;
>
> + Status = MpServicesUnitTestStartupThisAP (
>
> + LocalContext->MpServices,
>
> + (EFI_AP_PROCEDURE)RunMpServiceSwitchBSPOnAp,
>
> + ApNumber,
>
> + 0,
>
> + (VOID *)LocalContext
>
> + );
>
> +
>
> + if (ApNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When switch a disabled AP to be BSP, the return status should be EFI_INVALID_PARAMETER.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NewBspNumber;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) {
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + FALSE,
>
> + NULL
>
> + );
>
> +
>
> + if (NewBspNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + TRUE
>
> + );
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the enabled state and the old BSP should
>
> + be in the enabled state.
>
> + When SwitchBSP and EnableOldBSP is False, the new BSP should be in the enabled state and the old BSP should
>
> + be in the disabled state.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN NewBspNumber;
>
> + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
>
> + MP_SERVICE_UT_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MP_SERVICE_UT_CONTEXT *)Context;
>
> +
>
> + for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) {
>
> + Status = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + FALSE
>
> + );
>
> +
>
> + if (NewBspNumber == LocalContext->BspNumber) {
>
> + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
>
> + } else {
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (
>
> + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
>
> + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
>
> + );
>
> +
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + LocalContext->BspNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (
>
> + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
>
> + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
>
> + );
>
> +
>
> + Status = MpServicesUnitTestEnableDisableAP (
>
> + LocalContext->MpServices,
>
> + LocalContext->BspNumber,
>
> + TRUE,
>
> + NULL
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestSwitchBSP (
>
> + LocalContext->MpServices,
>
> + LocalContext->BspNumber,
>
> + TRUE
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> +
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + LocalContext->BspNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (
>
> + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
>
> + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
>
> + );
>
> +
>
> + Status = MpServicesUnitTestGetProcessorInfo (
>
> + LocalContext->MpServices,
>
> + NewBspNumber,
>
> + &ProcessorInfoBuffer
>
> + );
>
> + UT_ASSERT_NOT_EFI_ERROR (Status);
>
> + UT_ASSERT_TRUE (
>
> + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) &&
>
> + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)
>
> + );
>
> + }
>
> + }
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
>
> +
>
> + @param[in] Framework A pointer to the framework that is being persisted.
>
> + @param[in] Context A pointer to the private data buffer.
>
> +
>
> + @retval EFI_SUCCESS Create test suite and unit tests successfully.
>
> + @retval Others Create test suite and unit tests unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +AddCommonTestCase (
>
> + IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
>
> + IN MP_SERVICE_UT_CONTEXT *Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceWhoAmITestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceGetNumberOfProcessorsTestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceGetProcessorInfoTestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceEnableDisableAPTestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceStartupThisAPTestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceStartupAllAPsTestSuite;
>
> + UNIT_TEST_SUITE_HANDLE MpServiceSwitchBSPTestSuite;
>
> +
>
> + MpServiceWhoAmITestSuite = NULL;
>
> + MpServiceGetNumberOfProcessorsTestSuite = NULL;
>
> + MpServiceGetProcessorInfoTestSuite = NULL;
>
> + MpServiceEnableDisableAPTestSuite = NULL;
>
> + MpServiceStartupThisAPTestSuite = NULL;
>
> + MpServiceStartupAllAPsTestSuite = NULL;
>
> + MpServiceSwitchBSPTestSuite = NULL;
>
> +
>
> + //
>
> + // Test WhoAmI function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceWhoAmITestSuite, Framework, "Identify the currently executing processor",
> "MpServices.WhoAmI", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceWhoAmI Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceWhoAmITestSuite, "Test WhoAmI 1", "TestWhoAmI1", TestWhoAmI1, InitUTContext,
> CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test GetNumberOfProcessors function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceGetNumberOfProcessorsTestSuite, Framework, "Retrieve the number of
> logical processor", "MpServices.GetNumberOfProcessors", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetNumberOfProcessors Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 1",
> "TestGetNumberOfProcessors1", TestGetNumberOfProcessors1, InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 2",
> "TestGetNumberOfProcessors2", TestGetNumberOfProcessors2, InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 3",
> "TestGetNumberOfProcessors3", TestGetNumberOfProcessors3, InitUTContext, CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test GetProcessorInfo function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceGetProcessorInfoTestSuite, Framework, "Get detailed information on the
> requested logical processor", "MpServices.GetProcessorInfo", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetProcessorInfo Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 1", "TestGetProcessorInfo1",
> TestGetProcessorInfo1, InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 2", "TestGetProcessorInfo2",
> TestGetProcessorInfo2, InitUTContext, CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test EnableDisableAP function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceEnableDisableAPTestSuite, Framework, "Caller enables or disables an AP from
> this point onward", "MpServices.EnableDisableAP", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceEnableDisableAP Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 1", "TestEnableDisableAP1",
> TestEnableDisableAP1, InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 2", "TestEnableDisableAP2",
> TestEnableDisableAP2, InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 3", "TestEnableDisableAP3",
> TestEnableDisableAP3, InitUTContext, CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test StartupThisAP function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceStartupThisAPTestSuite, Framework, "Get the requested AP to execute a
> caller-provided function", "MpServices.StartupThisAP", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupThisAP Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 1", "TestStartupThisAP1", TestStartupThisAP1,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 2", "TestStartupThisAP2", TestStartupThisAP2,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 3", "TestStartupThisAP3", TestStartupThisAP3,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 4", "TestStartupThisAP4", TestStartupThisAP4,
> InitUTContext, CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test StartupAllAPs function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceStartupAllAPsTestSuite, Framework, "Execute a caller provided function on all
> enabled APs", "MpServices.StartupAllAPs", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupAllAPs Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 1", "TestStartupAllAPs1", TestStartupAllAPs1,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 2", "TestStartupAllAPs2", TestStartupAllAPs2,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 3", "TestStartupAllAPs3", TestStartupAllAPs3,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 4", "TestStartupAllAPs4", TestStartupAllAPs4,
> InitUTContext, CheckUTContext, Context);
>
> + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 5", "TestStartupAllAPs5", TestStartupAllAPs5,
> InitUTContext, CheckUTContext, Context);
>
> +
>
> + //
>
> + // Test SwitchBSP function
>
> + //
>
> + Status = CreateUnitTestSuite (&MpServiceSwitchBSPTestSuite, Framework, "Switch the requested AP to be the BSP
> from that point onward", "MpServices.SwitchBSP", NULL, NULL);
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceSwitchBSP Test Suite\n"));
>
> + return Status;
>
> + }
>
> +
>
> + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 1", "TestSwitchBSP1", TestSwitchBSP1, InitUTContext,
> CheckUTContext, Context);
>
> + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 2", "TestSwitchBSP2", TestSwitchBSP2, InitUTContext,
> CheckUTContext, Context);
>
> + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 3", "TestSwitchBSP3", TestSwitchBSP3, InitUTContext,
> CheckUTContext, Context);
>
> + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 4", "TestSwitchBSP4", TestSwitchBSP4, InitUTContext,
> FreeUTContext, Context);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
> new file mode 100644
> index 0000000000..0b2ddc5585
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
> @@ -0,0 +1,46 @@
> +## @file
>
> +# PEIM that unit tests the EdkiiPeiMpServices2Ppi
>
> +#
>
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010005
>
> + BASE_NAME = EdkiiPeiMpServices2PpiPeiUnitTest
>
> + FILE_GUID = A4914810-4D1E-445E-BD6F-F6821B852B5D
>
> + MODULE_TYPE = PEIM
>
> + VERSION_STRING = 1.0
>
> + ENTRY_POINT = PeiEntryPoint
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + EfiMpServicesUnitTestCommom.c
>
> + EfiMpServicesUnitTestCommom.h
>
> + EdkiiPeiMpServices2PpiUnitTest.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + UefiCpuPkg/UefiCpuPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + DebugLib
>
> + BaseMemoryLib
>
> + MemoryAllocationLib
>
> + PeimEntryPoint
>
> + PeiServicesLib
>
> + UnitTestPersistenceLib
>
> + UnitTestLib
>
> +
>
> +[Ppis]
>
> + gEdkiiPeiMpServices2PpiGuid ## CONSUMES
>
> +
>
> +[Depex]
>
> + gEdkiiPeiMpServices2PpiGuid
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
> new file mode 100644
> index 0000000000..1389092c06
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
> @@ -0,0 +1,46 @@
> +## @file
>
> +# DXE driver that unit tests the EfiMpServiceProtocol
>
> +#
>
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010005
>
> + BASE_NAME = EfiMpServiceProtocolDxeUnitTest
>
> + FILE_GUID = F1E468E2-A32D-4574-895D-6D82B27B08BC
>
> + MODULE_TYPE = DXE_DRIVER
>
> + VERSION_STRING = 1.0
>
> + ENTRY_POINT = DxeEntryPoint
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + EfiMpServicesUnitTestCommom.c
>
> + EfiMpServicesUnitTestCommom.h
>
> + EfiMpServiceProtocolUnitTest.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + UefiCpuPkg/UefiCpuPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + DebugLib
>
> + BaseMemoryLib
>
> + MemoryAllocationLib
>
> + UefiDriverEntryPoint
>
> + UefiBootServicesTableLib
>
> + UnitTestPersistenceLib
>
> + UnitTestLib
>
> +
>
> +[Protocols]
>
> + gEfiMpServiceProtocolGuid ## CONSUMES
>
> +
>
> +[Depex]
>
> + gEfiMpServiceProtocolGuid
>
> diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h
> b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h
> new file mode 100644
> index 0000000000..abbbd2faba
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h
> @@ -0,0 +1,627 @@
> +/** @file
>
> + Common header file for EfiMpServiceProtocolUnitTest DXE driver.
>
> +
>
> + Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
>
> +
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_
>
> +#define EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_
>
> +
>
> +#include <PiPei.h>
>
> +#include <Ppi/MpServices2.h>
>
> +#include <Protocol/MpService.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/ReportStatusCodeLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/UnitTestLib.h>
>
> +
>
> +#define RUN_PROCEDURE_TIMEOUT_VALUE 100000 // microseconds
>
> +
>
> +typedef union {
>
> + EDKII_PEI_MP_SERVICES2_PPI *Ppi;
>
> + EFI_MP_SERVICES_PROTOCOL *Protocol;
>
> +} MP_SERVICES;
>
> +
>
> +typedef struct {
>
> + MP_SERVICES MpServices;
>
> + UINTN BspNumber;
>
> + UINTN ApNumber;
>
> + UINTN NumberOfProcessors;
>
> + UINTN NumberOfEnabledProcessors;
>
> + UINTN *CommonBuffer;
>
> + EFI_STATUS ApProcedureReturnStatus;
>
> + UINTN *DisabledApNumber;
>
> +} MP_SERVICE_UT_CONTEXT;
>
> +
>
> +/**
>
> + Get EFI_MP_SERVICES_PROTOCOL pointer.
>
> +
>
> + @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored
>
> +
>
> + @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned
>
> + @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetMpServices (
>
> + OUT MP_SERVICES *MpServices
>
> + );
>
> +
>
> +/**
>
> + Retrieve the number of logical processor in the platform and the number of those logical processors that
>
> + are enabled on this boot.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system, including
>
> + the BSP and disabled APs.
>
> + @param[out] NumberOfEnabledProcessors Pointer to the number of processors in the system that are enabled.
>
> +
>
> + @retval EFI_SUCCESS Retrieve the number of logical processor successfully
>
> + @retval Others Retrieve the number of logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetNumberOfProcessors (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *NumberOfProcessors,
>
> + OUT UINTN *NumberOfEnabledProcessors
>
> + );
>
> +
>
> +/**
>
> + Get detailed information on the requested logical processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the processor.
>
> + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processor information is stored.
>
> +
>
> + @retval EFI_SUCCESS Get information on the requested logical processor successfully
>
> + @retval Others Get information on the requested logical processor unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestGetProcessorInfo (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
>
> + );
>
> +
>
> +/**
>
> + Execute a caller provided function on all enabled APs.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] SingleThread If TRUE, then all the enabled APs execute the function specified by Procedure
>
> + one by one, in ascending order of processor handle number.
>
> + If FALSE, then all the enabled APs execute the function specified by Procedure
>
> + simultaneously.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> + @retval EFI_SUCCESS Execute a caller provided function on all enabled APs successfully
>
> + @retval Others Execute a caller provided function on all enabled APs unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupAllAPs (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN BOOLEAN SingleThread,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + );
>
> +
>
> +/**
>
> + Caller gets one enabled AP to execute a caller-provided function.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] Procedure Pointer to the function to be run on enabled APs of the system.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] TimeoutInMicroSeconds Indicates the time limit in microseconds for APs to return from Procedure,
>
> + for blocking mode only. Zero means infinity.
>
> + @param[in] ProcedureArgument The parameter passed into Procedure for all APs.
>
> +
>
> + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller-provided function successfully
>
> + @retval Others Caller gets one enabled AP to execute a caller-provided function unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestStartupThisAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN EFI_AP_PROCEDURE Procedure,
>
> + IN UINTN ProcessorNumber,
>
> + IN UINTN TimeoutInMicroSeconds,
>
> + IN VOID *ProcedureArgument
>
> + );
>
> +
>
> +/**
>
> + Switch the requested AP to be the BSP from that point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
>
> + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enabled AP. Otherwise, it will be disabled.
>
> +
>
> + @retval EFI_SUCCESS Switch the requested AP to be the BSP successfully
>
> + @retval Others Switch the requested AP to be the BSP unsuccessfully
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestSwitchBSP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableOldBSP
>
> + );
>
> +
>
> +/**
>
> + Caller enables or disables an AP from this point onward.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[in] ProcessorNumber The handle number of the AP.
>
> + @param[in] EnableAP Specifies the new state for the processor for enabled, FALSE for disabled.
>
> + @param[in] HealthFlag If not NULL, a pointer to a value that specifies the new health status of the AP.
>
> +
>
> + @retval EFI_SUCCESS Caller enables or disables an AP successfully.
>
> + @retval Others Caller enables or disables an AP unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestEnableDisableAP (
>
> + IN MP_SERVICES MpServices,
>
> + IN UINTN ProcessorNumber,
>
> + IN BOOLEAN EnableAP,
>
> + IN UINT32 *HealthFlag
>
> + );
>
> +
>
> +/**
>
> + Get the handle number for the calling processor.
>
> +
>
> + @param[in] MpServices MP_SERVICES structure.
>
> + @param[out] ProcessorNumber The handle number for the calling processor.
>
> +
>
> + @retval EFI_SUCCESS Get the handle number for the calling processor successfully.
>
> + @retval Others Get the handle number for the calling processor unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +MpServicesUnitTestWhoAmI (
>
> + IN MP_SERVICES MpServices,
>
> + OUT UINTN *ProcessorNumber
>
> + );
>
> +
>
> +/**
>
> + Empty procedure to be run on specified CPU.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +EmptyProcedure (
>
> + IN OUT VOID *Buffer
>
> + );
>
> +
>
> +/**
>
> + Produce to store ProcessorNumber in CommonBuffer and be run on specified CPU.
>
> +
>
> + @param[in,out] Buffer The pointer to private data buffer.
>
> +**/
>
> +VOID
>
> +StoreCpuNumbers (
>
> + IN OUT VOID *Buffer
>
> + );
>
> +
>
> +/**
>
> + Prep routine for Unit test function.
>
> + To save the ProcessorNumber of disabled AP and temporarily enable it.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED Prep routine runs successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Cleanup routine for Unit test function.
>
> + If any processor is disabled unexpectedly then reenable it.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +CheckUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Cleanup routine for Unit test function.
>
> + It will be called by the last "AddTestCase" to restore AP state and free pointer.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +FreeUTContext (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service WhoAmI.
>
> + The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1.
>
> + The ProcessorNumbers of all CPUs are unique.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestWhoAmI1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + NumberOfProcessors should be greater that 0 and not less than NumberOfEnabledProcessors.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service GetNumberOfProcessors.
>
> + Call EnableDisableAP() to change the number of enabled AP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetNumberOfProcessors3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service GetProcessorInfo.
>
> + When all the parameters are valid, all reserved bits of StatusFlag in ProcessorInfoBuffer should be set to zero.
>
> + When all the parameters are valid, the StatusFlag should not have an invalid value (The BSP can never be in the disabled
> state.).
>
> + When called with nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetProcessorInfo1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service GetProcessorInfo.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestGetProcessorInfo2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When called with BSP number, the return status should be EFI_INVALID_PARAMETER.
>
> + When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> + The AP should be really Enable/Disabled.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service EnableDisableAP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestEnableDisableAP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When called to startup a BSP, the return status should be EFI_INVALID_PARAMETER.
>
> + When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND.
>
> + The requested AP should execute the Procedure when called by StartupThisAP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When timeout expired before the requested AP has finished, the return status should be EFI_TIMEOUT.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupThisAP.
>
> + When called with disabled AP, the return status should be EFI_INVALID_PARAMETER.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupThisAP4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + All APs should execute the Procedure when called by StartupAllAPs.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called in single thread, the return status should be EFI_SUCCESS and AP executes in ascending order
>
> + of processor handle number.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When this service is called from an AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called with all AP timeout, the return status should be EFI_TIMEOUT.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service StartupAllAPs.
>
> + When called with the empty Procedure on all disabled APs, the return status should be EFI_NOT_STARTED.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestStartupAllAPs5 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When switch current BSP to be BSP, the return status should be EFI_INVALID_PARAMETER.
>
> + When switch nonexistent processor to be BSP, the return status should be EFI_NOT_FOUND.
>
> + After switch BSP, all APs(includes new AP) should execute the Procedure when called by StartupAllAP.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP1 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When run this procedure on AP, the return status should be EFI_DEVICE_ERROR.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP2 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When switch a disabled AP to be BSP, the return status should be EFI_INVALID_PARAMETER.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP3 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Unit test of MP service SwitchBSP.
>
> + When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the enabled state and the old BSP should
>
> + be in the enabled state.
>
> + When SwitchBSP and EnableOldBSP is False, the new BSP should be in the enabled state and the old BSP should
>
> + be in the disabled state.
>
> +
>
> + @param[in] Context Context pointer for this test.
>
> +
>
> + @retval UNIT_TEST_PASSED The Unit test has completed and the test
>
> + case was successful.
>
> + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +TestSwitchBSP4 (
>
> + IN UNIT_TEST_CONTEXT Context
>
> + );
>
> +
>
> +/**
>
> + Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol.
>
> +
>
> + @param[in] Framework A pointer to the framework that is being persisted.
>
> + @param[in] Context A pointer to the private data buffer.
>
> +
>
> + @retval EFI_SUCCESS Create test suite and unit tests successfully.
>
> + @retval Others Create test suite and unit tests unsuccessfully.
>
> +**/
>
> +EFI_STATUS
>
> +AddCommonTestCase (
>
> + IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
>
> + IN MP_SERVICE_UT_CONTEXT *Context
>
> + );
>
> +
>
> +#endif
>
> diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> index f694b3a77c..db5fe654b5 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -63,6 +63,9 @@
> MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
>
> SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
>
> CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
>
> + UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf
>
> + UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
>
> + UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf
>
>
>
> [LibraryClasses.common.SEC]
>
> PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
>
> @@ -177,6 +180,8 @@
> UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
>
> UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
>
> UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
>
> + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPeiUnitTest.inf
>
> + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf
>
>
>
> [BuildOptions]
>
> *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
>
> --
> 2.28.0.windows.1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-10-14 6:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-10 13:52 [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol Jason Lou
2022-10-14 6:18 ` Ni, Ray
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox