]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCommom.c
UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol
[mirror_edk2.git] / UefiCpuPkg / Test / UnitTest / EfiMpServicesPpiProtocol / EfiMpServicesUnitTestCommom.c
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