/** @file Common code to test EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol. Copyright (c) 2022, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "EfiMpServicesUnitTestCommom.h" /** Prep routine for Unit test function. To save the ProcessorNumber of disabled AP and temporarily enable it. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED Prep routine runs successful. @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful. **/ UNIT_TEST_STATUS EFIAPI InitUTContext ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NumberOfProcessors; UINTN NumberOfEnabledProcessors; UINTN NumberOfDisabledAPs; UINTN IndexOfDisabledAPs; UINTN BspNumber; UINTN ProcessorNumber; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; if (LocalContext->MpServices.Ppi != NULL) { return UNIT_TEST_PASSED; } Status = MpServicesUnitTestGetMpServices (&LocalContext->MpServices); UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber); UT_ASSERT_NOT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, "%a: BspNumber = 0x%x\n", __func__, BspNumber)); Status = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); UT_ASSERT_NOT_EFI_ERROR (Status); DEBUG (( DEBUG_INFO, "%a: NumberOfProcessors = 0x%x, NumberOfEnabledProcessors = 0x%x\n", __func__, NumberOfProcessors, NumberOfEnabledProcessors )); LocalContext->BspNumber = BspNumber; LocalContext->NumberOfProcessors = NumberOfProcessors; LocalContext->NumberOfEnabledProcessors = NumberOfEnabledProcessors; LocalContext->CommonBuffer = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*LocalContext->CommonBuffer))); UT_ASSERT_NOT_NULL (LocalContext->CommonBuffer); NumberOfDisabledAPs = NumberOfProcessors - NumberOfEnabledProcessors; if ((NumberOfDisabledAPs > 0) && (LocalContext->DisabledApNumber == NULL)) { LocalContext->DisabledApNumber = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber))); UT_ASSERT_NOT_NULL (LocalContext->DisabledApNumber); ZeroMem (LocalContext->DisabledApNumber, NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber)); for (ProcessorNumber = 0, IndexOfDisabledAPs = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) { Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, ProcessorNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) { // // Save ProcessorNumber of disabled AP. // LocalContext->DisabledApNumber[IndexOfDisabledAPs] = ProcessorNumber; IndexOfDisabledAPs++; DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enable it.\n", __func__, ProcessorNumber)); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ProcessorNumber, TRUE, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); } } UT_ASSERT_TRUE (IndexOfDisabledAPs == NumberOfDisabledAPs); } return UNIT_TEST_PASSED; } /** Cleanup routine for Unit test function. If any processor is disabled unexpectedly then reenable it. @param[in] Context Context pointer for this test. **/ VOID EFIAPI CheckUTContext ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NumberOfProcessors; UINTN NumberOfEnabledProcessors; UINTN BspNumber; UINTN ProcessorNumber; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; ASSERT (LocalContext->MpServices.Ppi != NULL); Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumber); ASSERT_EFI_ERROR (Status); if (BspNumber != LocalContext->BspNumber) { LocalContext->BspNumber = BspNumber; DEBUG ((DEBUG_INFO, "%a: New BspNumber = 0x%x\n", __func__, BspNumber)); } ASSERT (BspNumber == LocalContext->BspNumber); Status = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); ASSERT_EFI_ERROR (Status); if (NumberOfProcessors != LocalContext->NumberOfProcessors) { LocalContext->NumberOfProcessors = NumberOfProcessors; DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors = 0x%x\n", __func__, NumberOfProcessors)); } if (NumberOfEnabledProcessors != LocalContext->NumberOfProcessors) { DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors = 0x%x\n", __func__, NumberOfEnabledProcessors)); for (ProcessorNumber = 0; ProcessorNumber < LocalContext->NumberOfProcessors; ProcessorNumber++) { Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, ProcessorNumber, &ProcessorInfoBuffer ); ASSERT_EFI_ERROR (Status); if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) { DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and reenable it.\n", __func__, ProcessorNumber)); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ProcessorNumber, TRUE, NULL ); ASSERT_EFI_ERROR (Status); } } } } /** Cleanup routine for Unit test function. It will be called by the last "AddTestCase" to restore AP state and free pointer. @param[in] Context Context pointer for this test. **/ VOID EFIAPI FreeUTContext ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NumberOfDisabledAPs; UINTN IndexOfDisabledAPs; MP_SERVICE_UT_CONTEXT *LocalContext; CheckUTContext (Context); LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; ASSERT (LocalContext->MpServices.Ppi != NULL); if (LocalContext->DisabledApNumber != NULL) { NumberOfDisabledAPs = LocalContext->NumberOfProcessors - LocalContext->NumberOfEnabledProcessors; for (IndexOfDisabledAPs = 0; IndexOfDisabledAPs < NumberOfDisabledAPs; IndexOfDisabledAPs++) { DEBUG (( DEBUG_INFO, "%a: Disable AP(0x%x) to restore its state.\n", __func__, LocalContext->DisabledApNumber[IndexOfDisabledAPs] )); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, LocalContext->DisabledApNumber[IndexOfDisabledAPs], FALSE, NULL ); ASSERT_EFI_ERROR (Status); } FreePages (LocalContext->DisabledApNumber, EFI_SIZE_TO_PAGES (NumberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber))); } if (LocalContext->CommonBuffer != NULL) { FreePages (LocalContext->CommonBuffer, EFI_SIZE_TO_PAGES (LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer))); } } /** Produce to store ProcessorNumber in the corresponding location of CommonBuffer. @param[in,out] Buffer The pointer to private data buffer. **/ VOID StoreCpuNumbers ( IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN ProcessorNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber); ASSERT_EFI_ERROR (Status); // // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6) // Index 00 01 02 03 04 05 // Value 00 01 02 03 04 05 // if (ProcessorNumber < LocalContext->NumberOfProcessors) { LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber; } } /** Produce to store the ProcessorNumber of AP execution order in CommonBuffer. @param[in,out] Buffer The pointer to private data buffer. **/ VOID StoreAPsExecutionOrder ( IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN ProcessorNumber; UINTN *ApCounter; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; Status = MpServicesUnitTestWhoAmI (LocalContext->MpServices, &ProcessorNumber); ASSERT_EFI_ERROR (Status); // // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6) // Index 00 01 02 03 04 05 // Value 00 01 03 04 05 ApCounter(5) // ApCounter = &(LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1]); LocalContext->CommonBuffer[*ApCounter] = ProcessorNumber; (*ApCounter)++; } /** Infinite loop procedure to be run on specified CPU. @param[in,out] Buffer The pointer to private data buffer. **/ VOID InfiniteLoopProcedure ( IN OUT VOID *Buffer ) { volatile BOOLEAN InfiniteLoop; InfiniteLoop = TRUE; while (InfiniteLoop) { } } /** Empty procedure to be run on specified CPU. @param[in,out] Buffer The pointer to private data buffer. **/ VOID EmptyProcedure ( IN OUT VOID *Buffer ) { } /** Procedure to run MP service GetNumberOfProcessors on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceGetNumberOfProcessorsOnAp ( IN OUT VOID *Buffer ) { UINTN NumberOfProcessors; UINTN NumberOfEnabledProcessors; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); } /** Procedure to run MP service GetProcessorInfo on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceGetProcessorInfoOnAp ( IN OUT VOID *Buffer ) { EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, LocalContext->ApNumber, &ProcessorInfoBuffer ); } /** Procedure to run MP service EnableDisableAP on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceEnableDisableAPOnAp ( IN OUT VOID *Buffer ) { MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, LocalContext->ApNumber, FALSE, NULL ); } /** Procedure to run MP service StartupThisAP on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceStartupThisAPOnAp ( IN OUT VOID *Buffer ) { MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, LocalContext->ApNumber, 0, NULL ); } /** Procedure to run MP service StartupAllAPs on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceStartupAllAPsOnAp ( IN OUT VOID *Buffer ) { MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, FALSE, 0, NULL ); } /** Procedure to run MP service SwitchBSP on AP. @param[in,out] Buffer The pointer to private data buffer. **/ VOID RunMpServiceSwitchBSPOnAp ( IN OUT VOID *Buffer ) { MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Buffer; LocalContext->ApProcedureReturnStatus = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, LocalContext->ApNumber, TRUE ); } /** Unit test of MP service WhoAmI. The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1. The ProcessorNumbers of all CPUs are unique. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestWhoAmI1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ProcessorNumber; UINTN ProcessorIndex; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; Status = MpServicesUnitTestWhoAmI ( LocalContext->MpServices, &ProcessorNumber ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE (ProcessorNumber < LocalContext->NumberOfProcessors); SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF); LocalContext->CommonBuffer[ProcessorNumber] = ProcessorNumber; Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)StoreCpuNumbers, FALSE, 0, (VOID *)LocalContext ); UT_ASSERT_NOT_EFI_ERROR (Status); // // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6) // Index 00 01 02 03 04 05 // Value 00 01 02 03 04 05 // for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) { UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex); } return UNIT_TEST_PASSED; } /** Unit test of MP service GetNumberOfProcessors. NumberOfProcessors should be greater that 0 and not less than NumberOfEnabledProcessors. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestGetNumberOfProcessors1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NumberOfProcessors; UINTN NumberOfEnabledProcessors; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; Status = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE (NumberOfProcessors > 0 && NumberOfProcessors >= NumberOfEnabledProcessors); return UNIT_TEST_PASSED; } /** Unit test of MP service GetNumberOfProcessors. When this service is called from an AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestGetNumberOfProcessors2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceGetNumberOfProcessorsOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service GetNumberOfProcessors. Call EnableDisableAP() to change the number of enabled AP. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestGetNumberOfProcessors3 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; UINTN NumberOfProcessors; UINTN NumberOfEnabledProcessors; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, FALSE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors); if (ApNumber < LocalContext->BspNumber) { UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - (ApNumber + 1)); } else { UT_ASSERT_TRUE (NumberOfEnabledProcessors == LocalContext->NumberOfProcessors - ApNumber); } } } for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestGetNumberOfProcessors ( LocalContext->MpServices, &NumberOfProcessors, &NumberOfEnabledProcessors ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE (NumberOfProcessors == LocalContext->NumberOfProcessors); if (ApNumber < LocalContext->BspNumber) { UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 2); } else { UT_ASSERT_TRUE (NumberOfEnabledProcessors == ApNumber + 1); } } } return UNIT_TEST_PASSED; } /** Unit test of MP service GetProcessorInfo. When all the parameters are valid, all reserved bits of StatusFlag in ProcessorInfoBuffer should be set to zero. When all the parameters are valid, the StatusFlag should not have an invalid value (The BSP can never be in the disabled state.). When called with nonexistent processor handle, the return status should be EFI_NOT_FOUND. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestGetProcessorInfo1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ProcessorNumber; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ProcessorNumber = 0; ProcessorNumber <= LocalContext->NumberOfProcessors; ProcessorNumber++) { Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, ProcessorNumber, &ProcessorInfoBuffer ); if (ProcessorNumber == LocalContext->NumberOfProcessors) { UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & (UINT32) ~(PROCESSOR_AS_BSP_BIT|PROCESSOR_ENABLED_BIT|PROCESSOR_HEALTH_STATUS_BIT)) == 0); if (ProcessorNumber == LocalContext->BspNumber) { UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)); } else { UT_ASSERT_TRUE (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT)); } } } return UNIT_TEST_PASSED; } /** Unit test of MP service GetProcessorInfo. When this service is called from an AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestGetProcessorInfo2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceGetProcessorInfoOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service EnableDisableAP. When called with BSP number, the return status should be EFI_INVALID_PARAMETER. When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND. The AP should be really Enable/Disabled. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestEnableDisableAP1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, FALSE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else if (ApNumber == LocalContext->NumberOfProcessors) { UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, ApNumber, 0, NULL ); UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, ApNumber, 0, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service EnableDisableAP. When run this procedure on AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestEnableDisableAP2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceEnableDisableAPOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service EnableDisableAP. When run this procedure on AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestEnableDisableAP3 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; UINT32 OldHealthFlag; UINT32 NewHealthFlag; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, ApNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); OldHealthFlag = ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT; NewHealthFlag = OldHealthFlag ^ PROCESSOR_HEALTH_STATUS_BIT; Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, &NewHealthFlag ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, ApNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) == NewHealthFlag); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, &OldHealthFlag ); UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupThisAP. When called to startup a BSP, the return status should be EFI_INVALID_PARAMETER. When called with a nonexistent processor handle, the return status should be EFI_NOT_FOUND. The requested AP should execute the Procedure when called by StartupThisAP. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupThisAP1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; UINTN ProcessorIndex; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber <= LocalContext->NumberOfProcessors; ApNumber++) { SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF); Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)StoreCpuNumbers, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else if (ApNumber == LocalContext->NumberOfProcessors) { UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); } else { UT_ASSERT_NOT_EFI_ERROR (Status); for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) { UT_ASSERT_TRUE ( ((ProcessorIndex == ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex)) || ((ProcessorIndex != ApNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) ); } } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupThisAP. When this service is called from an AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupThisAP2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceStartupThisAPOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupThisAP. When timeout expired before the requested AP has finished, the return status should be EFI_TIMEOUT. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupThisAP3 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)InfiniteLoopProcedure, ApNumber, RUN_PROCEDURE_TIMEOUT_VALUE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupThisAP. When called with disabled AP, the return status should be EFI_INVALID_PARAMETER. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupThisAP4 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, FALSE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, ApNumber, 0, NULL ); UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, ApNumber, 0, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupAllAPs. All APs should execute the Procedure when called by StartupAllAPs. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupAllAPs1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ProcessorIndex; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF); Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)StoreCpuNumbers, FALSE, 0, (VOID *)LocalContext ); UT_ASSERT_NOT_EFI_ERROR (Status); for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) { UT_ASSERT_TRUE ( ((ProcessorIndex == LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) || ((ProcessorIndex != LocalContext->BspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex)) ); } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupAllAPs. When called in single thread, the return status should be EFI_SUCCESS and AP executes in ascending order of processor handle number. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupAllAPs2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ProcessorIndex; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; ZeroMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer)); Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)StoreAPsExecutionOrder, TRUE, 0, (VOID *)LocalContext ); UT_ASSERT_NOT_EFI_ERROR (Status); // // The layout of CommonBuffer (E.g. BspNumber = 2 and NumberOfProcessors = 6) // Index 00 01 02 03 04 05 // Value 00 01 03 04 05 ApCounter(5) // for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors - 2; ProcessorIndex++) { UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] < LocalContext->CommonBuffer[ProcessorIndex + 1]); } UT_ASSERT_EQUAL (LocalContext->CommonBuffer[LocalContext->NumberOfProcessors - 1], LocalContext->NumberOfProcessors - 1); return UNIT_TEST_PASSED; } /** Unit test of MP service StartupAllAPs. When this service is called from an AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupAllAPs3 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceStartupAllAPsOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service StartupAllAPs. When called with all AP timeout, the return status should be EFI_TIMEOUT. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupAllAPs4 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)InfiniteLoopProcedure, TRUE, RUN_PROCEDURE_TIMEOUT_VALUE, NULL ); UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)InfiniteLoopProcedure, FALSE, RUN_PROCEDURE_TIMEOUT_VALUE, NULL ); UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); return UNIT_TEST_PASSED; } /** Unit test of MP service StartupAllAPs. When called with the empty Procedure on all disabled APs, the return status should be EFI_NOT_STARTED. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestStartupAllAPs5 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, FALSE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); } } Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)EmptyProcedure, FALSE, 0, NULL ); UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_STARTED); for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, ApNumber, TRUE, NULL ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service SwitchBSP. When switch current BSP to be BSP, the return status should be EFI_INVALID_PARAMETER. When switch nonexistent processor to be BSP, the return status should be EFI_NOT_FOUND. After switch BSP, all APs(includes new AP) should execute the Procedure when called by StartupAllAP. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestSwitchBSP1 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NewBspNumber; UINTN ProcessorIndex; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (NewBspNumber = 0; NewBspNumber <= LocalContext->NumberOfProcessors; NewBspNumber++) { Status = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, NewBspNumber, TRUE ); if (NewBspNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else if (NewBspNumber == LocalContext->NumberOfProcessors) { UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); } else { UT_ASSERT_NOT_EFI_ERROR (Status); SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer), 0xFF); Status = MpServicesUnitTestStartupAllAPs ( LocalContext->MpServices, (EFI_AP_PROCEDURE)StoreCpuNumbers, FALSE, 0, (VOID *)LocalContext ); UT_ASSERT_NOT_EFI_ERROR (Status); for (ProcessorIndex = 0; ProcessorIndex < LocalContext->NumberOfProcessors; ProcessorIndex++) { UT_ASSERT_TRUE ( ((ProcessorIndex == NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == (UINTN) ~0)) || ((ProcessorIndex != NewBspNumber) && (LocalContext->CommonBuffer[ProcessorIndex] == ProcessorIndex)) ); } Status = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, LocalContext->BspNumber, TRUE ); UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service SwitchBSP. When run this procedure on AP, the return status should be EFI_DEVICE_ERROR. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestSwitchBSP2 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN ApNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (ApNumber = 0; ApNumber < LocalContext->NumberOfProcessors; ApNumber++) { LocalContext->ApNumber = ApNumber; Status = MpServicesUnitTestStartupThisAP ( LocalContext->MpServices, (EFI_AP_PROCEDURE)RunMpServiceSwitchBSPOnAp, ApNumber, 0, (VOID *)LocalContext ); if (ApNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_DEVICE_ERROR); } } return UNIT_TEST_PASSED; } /** Unit test of MP service SwitchBSP. When switch a disabled AP to be BSP, the return status should be EFI_INVALID_PARAMETER. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestSwitchBSP3 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NewBspNumber; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) { Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, NewBspNumber, FALSE, NULL ); if (NewBspNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, NewBspNumber, TRUE ); UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, NewBspNumber, TRUE, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); } } return UNIT_TEST_PASSED; } /** Unit test of MP service SwitchBSP. When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the enabled state and the old BSP should be in the enabled state. When SwitchBSP and EnableOldBSP is False, the new BSP should be in the enabled state and the old BSP should be in the disabled state. @param[in] Context Context pointer for this test. @retval UNIT_TEST_PASSED The Unit test has completed and the test case was successful. @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. **/ UNIT_TEST_STATUS EFIAPI TestSwitchBSP4 ( IN UNIT_TEST_CONTEXT Context ) { EFI_STATUS Status; UINTN NewBspNumber; EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; MP_SERVICE_UT_CONTEXT *LocalContext; LocalContext = (MP_SERVICE_UT_CONTEXT *)Context; for (NewBspNumber = 0; NewBspNumber < LocalContext->NumberOfProcessors; NewBspNumber++) { Status = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, NewBspNumber, FALSE ); if (NewBspNumber == LocalContext->BspNumber) { UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); } else { UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, NewBspNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ( (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) ); Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, LocalContext->BspNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ( !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) ); Status = MpServicesUnitTestEnableDisableAP ( LocalContext->MpServices, LocalContext->BspNumber, TRUE, NULL ); UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestSwitchBSP ( LocalContext->MpServices, LocalContext->BspNumber, TRUE ); UT_ASSERT_NOT_EFI_ERROR (Status); Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, LocalContext->BspNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ( (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) ); Status = MpServicesUnitTestGetProcessorInfo ( LocalContext->MpServices, NewBspNumber, &ProcessorInfoBuffer ); UT_ASSERT_NOT_EFI_ERROR (Status); UT_ASSERT_TRUE ( !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) ); } } return UNIT_TEST_PASSED; } /** Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol. @param[in] Framework A pointer to the framework that is being persisted. @param[in] Context A pointer to the private data buffer. @retval EFI_SUCCESS Create test suite and unit tests successfully. @retval Others Create test suite and unit tests unsuccessfully. **/ EFI_STATUS AddCommonTestCase ( IN UNIT_TEST_FRAMEWORK_HANDLE Framework, IN MP_SERVICE_UT_CONTEXT *Context ) { EFI_STATUS Status; UNIT_TEST_SUITE_HANDLE MpServiceWhoAmITestSuite; UNIT_TEST_SUITE_HANDLE MpServiceGetNumberOfProcessorsTestSuite; UNIT_TEST_SUITE_HANDLE MpServiceGetProcessorInfoTestSuite; UNIT_TEST_SUITE_HANDLE MpServiceEnableDisableAPTestSuite; UNIT_TEST_SUITE_HANDLE MpServiceStartupThisAPTestSuite; UNIT_TEST_SUITE_HANDLE MpServiceStartupAllAPsTestSuite; UNIT_TEST_SUITE_HANDLE MpServiceSwitchBSPTestSuite; MpServiceWhoAmITestSuite = NULL; MpServiceGetNumberOfProcessorsTestSuite = NULL; MpServiceGetProcessorInfoTestSuite = NULL; MpServiceEnableDisableAPTestSuite = NULL; MpServiceStartupThisAPTestSuite = NULL; MpServiceStartupAllAPsTestSuite = NULL; MpServiceSwitchBSPTestSuite = NULL; // // Test WhoAmI function // Status = CreateUnitTestSuite (&MpServiceWhoAmITestSuite, Framework, "Identify the currently executing processor", "MpServices.WhoAmI", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceWhoAmI Test Suite\n")); return Status; } AddTestCase (MpServiceWhoAmITestSuite, "Test WhoAmI 1", "TestWhoAmI1", TestWhoAmI1, InitUTContext, CheckUTContext, Context); // // Test GetNumberOfProcessors function // Status = CreateUnitTestSuite (&MpServiceGetNumberOfProcessorsTestSuite, Framework, "Retrieve the number of logical processor", "MpServices.GetNumberOfProcessors", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetNumberOfProcessors Test Suite\n")); return Status; } AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 1", "TestGetNumberOfProcessors1", TestGetNumberOfProcessors1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 2", "TestGetNumberOfProcessors2", TestGetNumberOfProcessors2, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfProcessors 3", "TestGetNumberOfProcessors3", TestGetNumberOfProcessors3, InitUTContext, CheckUTContext, Context); // // Test GetProcessorInfo function // Status = CreateUnitTestSuite (&MpServiceGetProcessorInfoTestSuite, Framework, "Get detailed information on the requested logical processor", "MpServices.GetProcessorInfo", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetProcessorInfo Test Suite\n")); return Status; } AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 1", "TestGetProcessorInfo1", TestGetProcessorInfo1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo 2", "TestGetProcessorInfo2", TestGetProcessorInfo2, InitUTContext, CheckUTContext, Context); // // Test EnableDisableAP function // Status = CreateUnitTestSuite (&MpServiceEnableDisableAPTestSuite, Framework, "Caller enables or disables an AP from this point onward", "MpServices.EnableDisableAP", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceEnableDisableAP Test Suite\n")); return Status; } AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 1", "TestEnableDisableAP1", TestEnableDisableAP1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 2", "TestEnableDisableAP2", TestEnableDisableAP2, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 3", "TestEnableDisableAP3", TestEnableDisableAP3, InitUTContext, CheckUTContext, Context); // // Test StartupThisAP function // Status = CreateUnitTestSuite (&MpServiceStartupThisAPTestSuite, Framework, "Get the requested AP to execute a caller-provided function", "MpServices.StartupThisAP", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupThisAP Test Suite\n")); return Status; } AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 1", "TestStartupThisAP1", TestStartupThisAP1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 2", "TestStartupThisAP2", TestStartupThisAP2, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 3", "TestStartupThisAP3", TestStartupThisAP3, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 4", "TestStartupThisAP4", TestStartupThisAP4, InitUTContext, CheckUTContext, Context); // // Test StartupAllAPs function // Status = CreateUnitTestSuite (&MpServiceStartupAllAPsTestSuite, Framework, "Execute a caller provided function on all enabled APs", "MpServices.StartupAllAPs", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStartupAllAPs Test Suite\n")); return Status; } AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 1", "TestStartupAllAPs1", TestStartupAllAPs1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 2", "TestStartupAllAPs2", TestStartupAllAPs2, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 3", "TestStartupAllAPs3", TestStartupAllAPs3, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 4", "TestStartupAllAPs4", TestStartupAllAPs4, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 5", "TestStartupAllAPs5", TestStartupAllAPs5, InitUTContext, CheckUTContext, Context); // // Test SwitchBSP function // Status = CreateUnitTestSuite (&MpServiceSwitchBSPTestSuite, Framework, "Switch the requested AP to be the BSP from that point onward", "MpServices.SwitchBSP", NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceSwitchBSP Test Suite\n")); return Status; } AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 1", "TestSwitchBSP1", TestSwitchBSP1, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 2", "TestSwitchBSP2", TestSwitchBSP2, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 3", "TestSwitchBSP3", TestSwitchBSP3, InitUTContext, CheckUTContext, Context); AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 4", "TestSwitchBSP4", TestSwitchBSP4, InitUTContext, FreeUTContext, Context); return EFI_SUCCESS; }