]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol
authorJason Lou <yun.lou@intel.com>
Mon, 10 Oct 2022 13:52:42 +0000 (21:52 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 17 Oct 2022 08:03:06 +0000 (08:03 +0000)
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>
Reviewed-by: 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/EdkiiPeiMpServices2PpiPeiUnitTest.inf [new file with mode: 0644]
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUnitTest.c [new file with mode: 0644]
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeUnitTest.inf [new file with mode: 0644]
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnitTest.c [new file with mode: 0644]
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c [new file with mode: 0644]
UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.h [new file with mode: 0644]
UefiCpuPkg/UefiCpuPkg.dsc

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