From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) by mx.groups.io with SMTP id smtpd.web11.15028.1672846294303431741 for ; Wed, 04 Jan 2023 07:31:34 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=Mf+pfWvr; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: quicinc.com, ip: 205.220.168.131, mailfrom: quic_rcran@quicinc.com) Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 304DZBlW023808; Wed, 4 Jan 2023 15:31:25 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=qcppdkim1; bh=Wx4SRGoiZnKpiAFZqIhLG/rILrPXXSFKulYcrxprOio=; b=Mf+pfWvrt2s8CsqL1VB3gCrDlSASNo/gE00pvEzzZF3w/2EmuKl91GCrq1NWU4kv65M5 yoiNwv4zpOnghjQVdqRKO5HeH8uXKZA1vG+ernYv1nPjfMUZgVEfpcKkCe3xMnZClvoh ChpmOjtjelwLs+ttOu3h4+wL4gUGaiUB4bw6GmEcbvY69/DvisnoPogA/Fp3tOziTilY AdMUxU4r7BGlb7ORVaF+uO1G4CrxHno9gNZLwcS7+wlE/YXQQG1KzAL3Jdr6S4isX2Ri lKo/X3rNo2+NtvaN3r073Mc9IGDm4qIDvmyW8DXvjBjXFQsi1ImBAIB48/i/Jwgrzxpx xQ== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3mvsvej39q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 04 Jan 2023 15:31:25 +0000 Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 304FVOo4005618 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 4 Jan 2023 15:31:24 GMT Received: from linbox.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.36; Wed, 4 Jan 2023 07:31:24 -0800 From: Rebecca Cran To: , Sami Mujawar , "Ard Biesheuvel" , Leif Lindholm , Jian J Wang , Liming Gao CC: Rebecca Cran , Ard Biesheuvel Subject: [PATCH v3 3/3] MdeModulePkg: Add new Application/MpServicesTest application Date: Wed, 4 Jan 2023 08:30:56 -0700 Message-ID: <20230104153056.343258-4-rebecca@quicinc.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230104153056.343258-1-rebecca@quicinc.com> References: <20230104153056.343258-1-rebecca@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: RiytU6oKYyK1_r1R1bZ1qtUTfXR6hfS0 X-Proofpoint-ORIG-GUID: RiytU6oKYyK1_r1R1bZ1qtUTfXR6hfS0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.923,Hydra:6.0.545,FMLib:17.11.122.1 definitions=2023-01-04_07,2023-01-04_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 phishscore=0 malwarescore=0 bulkscore=0 adultscore=0 suspectscore=0 clxscore=1015 mlxscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301040130 Content-Transfer-Encoding: 8bit Content-Type: text/plain The MpServicesTest application exercises the EFI_MP_SERVICES_PROTOCOL. usage: MpServicesTest -A [-O] MpServicesTest -T MpServicesTest -S MpServicesTest -P MpServicesTest -U MpServicesTest -W MpServicesTest -E MpServicesTest -D MpServicesTest -h Parameter: -A: Run all APs. -O: Run APs sequentially (use with -A). -T: Specify timeout in milliseconds. Default is to wait forever. -S: Specify the single AP to run. -P: Print processor information. -U: Set the specified AP to the Unhealthy status (use with -E/-D). -W: Run WhoAmI and print index of BSP. -E: Enable the specified AP. -D: Disable the specified AP. -h: Print this help page. Signed-off-by: Rebecca Cran Reviewed-by: Ard Biesheuvel --- MdeModulePkg/MdeModulePkg.dsc | 2 + MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 40 ++ MdeModulePkg/Application/MpServicesTest/Options.h | 39 ++ MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 560 ++++++++++++++++++++ MdeModulePkg/Application/MpServicesTest/Options.c | 164 ++++++ 5 files changed, 805 insertions(+) diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 659482ab737f..6992b3ae8db6 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -166,6 +166,7 @@ [LibraryClasses.common.UEFI_APPLICATION] MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf [LibraryClasses.common.MM_STANDALONE] HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf @@ -445,6 +446,7 @@ [Components] MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf [Components.IA32, Components.X64, Components.AARCH64] + MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf MdeModulePkg/Universal/EbcDxe/EbcDxe.inf MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf MdeModulePkg/Universal/EbcDxe/EbcDebuggerConfig.inf diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf new file mode 100644 index 000000000000..07ee4afec845 --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf @@ -0,0 +1,40 @@ +## @file +# UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL. +# +# Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.29 + BASE_NAME = MpServicesTest + FILE_GUID = 43e9defa-7209-4b0d-b136-cc4ca02cb469 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 0.1 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources] + MpServicesTest.c + Options.c + Options.h + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + ShellLib + UefiApplicationEntryPoint + UefiLib + +[Protocols] + gEfiMpServiceProtocolGuid ## CONSUMES + diff --git a/MdeModulePkg/Application/MpServicesTest/Options.h b/MdeModulePkg/Application/MpServicesTest/Options.h new file mode 100644 index 000000000000..cb28230ab095 --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/Options.h @@ -0,0 +1,39 @@ +/** @file + Options handling code. + + Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef MPSERVICESTEST_OPTIONS_H_ +#define MPSERVICESTEST_OPTIONS_H_ + +#define INFINITE_TIMEOUT 0 + +typedef struct { + UINTN Timeout; + UINTN ProcessorIndex; + BOOLEAN RunAllAPs; + BOOLEAN RunSingleAP; + BOOLEAN DisableProcessor; + BOOLEAN EnableProcessor; + BOOLEAN SetProcessorHealthy; + BOOLEAN SetProcessorUnhealthy; + BOOLEAN PrintProcessorInformation; + BOOLEAN PrintBspProcessorIndex; + BOOLEAN RunAPsSequentially; +} MP_SERVICES_TEST_OPTIONS; + +/** + Parses any arguments provided on the command line. + + @param Options The arguments structure. + + @return EFI_SUCCESS on success, or an error code. +**/ +EFI_STATUS +ParseArguments ( + MP_SERVICES_TEST_OPTIONS *Options + ); + +#endif /* MPSERVICESTEST_OPTIONS_H_ */ diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c new file mode 100644 index 000000000000..3f3d9752d500 --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c @@ -0,0 +1,560 @@ +/** @file + UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL. + + Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Options.h" + +#define APFUNC_BUFFER_LEN 256 + +typedef struct { + EFI_MP_SERVICES_PROTOCOL *Mp; + CHAR16 **Buffer; +} APFUNC_ARG; + +/** The procedure to run with the MP Services interface. + + @param Arg The procedure argument. + +**/ +STATIC +VOID +EFIAPI +ApFunction ( + IN OUT VOID *Arg + ) +{ + APFUNC_ARG *Param; + UINTN ProcessorId; + + if (Arg != NULL) { + Param = Arg; + + Param->Mp->WhoAmI (Param->Mp, &ProcessorId); + UnicodeSPrint (Param->Buffer[ProcessorId], APFUNC_BUFFER_LEN, L"Hello from CPU %ld\n", ProcessorId); + } +} + +/** + Fetches the number of processors and which processor is the BSP. + + @param Mp MP Services Protocol. + @param NumProcessors Number of processors. + @param BspIndex The index of the BSP. +**/ +STATIC +EFI_STATUS +GetProcessorInformation ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + OUT UINTN *NumProcessors, + OUT UINTN *BspIndex + ) +{ + EFI_STATUS Status; + UINTN NumEnabledProcessors; + + Status = Mp->GetNumberOfProcessors (Mp, NumProcessors, &NumEnabledProcessors); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Mp->WhoAmI (Mp, BspIndex); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** Displays information returned from MP Services Protocol. + + @param Mp The MP Services Protocol + @param BspIndex On return, contains the index of the BSP. + + @return The number of CPUs in the system. + +**/ +STATIC +UINTN +PrintProcessorInformation ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + OUT UINTN *BspIndex + ) +{ + EFI_STATUS Status; + EFI_PROCESSOR_INFORMATION CpuInfo; + UINTN Index; + UINTN NumCpu; + UINTN NumEnabledCpu; + + Status = Mp->GetNumberOfProcessors (Mp, &NumCpu, &NumEnabledCpu); + if (EFI_ERROR (Status)) { + Print (L"GetNumberOfProcessors failed: %r\n", Status); + } else { + Print (L"Number of CPUs: %ld, Enabled: %d\n", NumCpu, NumEnabledCpu); + } + + for (Index = 0; Index < NumCpu; Index++) { + Status = Mp->GetProcessorInfo (Mp, CPU_V2_EXTENDED_TOPOLOGY | Index, &CpuInfo); + if (EFI_ERROR (Status)) { + Print (L"GetProcessorInfo for Processor %d failed: %r\n", Index, Status); + } else { + Print ( + L"Processor %d:\n" + L"\tID: %016lx\n" + L"\tStatus: %s | ", + Index, + CpuInfo.ProcessorId, + (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? L"BSP" : L"AP" + ); + + if ((CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) && (BspIndex != NULL)) { + *BspIndex = Index; + } + + Print (L"%s | ", (CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) ? L"Enabled" : L"Disabled"); + Print (L"%s\n", (CpuInfo.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted"); + + Print ( + L"\tLocation: Package %d, Core %d, Thread %d\n" + L"\tExtended Information: Package %d, Module %d, Tile %d, Die %d, Core %d, Thread %d\n\n", + CpuInfo.Location.Package, + CpuInfo.Location.Core, + CpuInfo.Location.Thread, + CpuInfo.ExtendedInformation.Location2.Package, + CpuInfo.ExtendedInformation.Location2.Module, + CpuInfo.ExtendedInformation.Location2.Tile, + CpuInfo.ExtendedInformation.Location2.Die, + CpuInfo.ExtendedInformation.Location2.Core, + CpuInfo.ExtendedInformation.Location2.Thread + ); + } + } + + return NumCpu; +} + +/** Allocates memory in ApArg for the single AP specified. + + @param ApArg Pointer to the AP argument structure. + @param Mp The MP Services Protocol. + @param ProcessorIndex The index of the AP. + + @retval EFI_SUCCESS Memory was successfully allocated. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + +**/ +STATIC +EFI_STATUS +AllocateApFuncBufferSingleAP ( + IN APFUNC_ARG *ApArg, + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN ProcessorIndex + ) +{ + ApArg->Mp = Mp; + + ApArg->Buffer = AllocateZeroPool ((ProcessorIndex + 1) * sizeof (VOID *)); + if (ApArg->Buffer == NULL) { + Print (L"Failed to allocate buffer for AP buffer\n"); + return EFI_OUT_OF_RESOURCES; + } + + ApArg->Buffer[ProcessorIndex] = AllocateZeroPool (APFUNC_BUFFER_LEN); + if (ApArg->Buffer[ProcessorIndex] == NULL) { + Print (L"Failed to allocate buffer for AP buffer\n"); + FreePool (ApArg->Buffer); + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** Allocates memory in ApArg for all APs. + + @param ApArg Pointer to the AP argument structure. + @param Mp The MP Services Protocol. + @param NumCpus The number of CPUs. + + @retval EFI_SUCCESS Memory was successfully allocated. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + +**/ +STATIC +EFI_STATUS +AllocateApFuncBufferAllAPs ( + IN APFUNC_ARG *ApArg, + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN NumCpus + ) +{ + UINT32 Index; + + ApArg->Mp = Mp; + + ApArg->Buffer = AllocateZeroPool (NumCpus * sizeof (VOID *)); + if (ApArg->Buffer == NULL) { + Print (L"Failed to allocate buffer for AP message\n"); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < NumCpus; Index++) { + ApArg->Buffer[Index] = AllocateZeroPool (APFUNC_BUFFER_LEN); + if (ApArg->Buffer[Index] == NULL) { + Print (L"Failed to allocate buffer for AP message\n"); + for (--Index; Index >= 0; Index++) { + FreePool (ApArg->Buffer[Index]); + } + + FreePool (ApArg->Buffer); + return EFI_OUT_OF_RESOURCES; + } + } + + return EFI_SUCCESS; +} + +/** Frees memory in ApArg for all APs. + + @param ApArg Pointer to the AP argument structure. + @param NumCpus The number of CPUs. + +**/ +STATIC +VOID +FreeApFuncBuffer ( + APFUNC_ARG *ApArg, + UINTN NumCpus + ) +{ + UINTN Index; + + for (Index = 0; Index < NumCpus; Index++) { + if (ApArg->Buffer[Index] != NULL) { + FreePool (ApArg->Buffer[Index]); + } + } + + FreePool (ApArg->Buffer); +} + +/** Runs a specified AP. + + @param Mp The MP Services Protocol. + @param ProcessorIndex The processor index. + @param Timeout Timeout in milliseconds. + + @return EFI_SUCCESS on success, or an error code. + +**/ +STATIC +EFI_STATUS +StartupThisAP ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN ProcessorIndex, + IN UINTN Timeout + ) +{ + EFI_STATUS Status; + APFUNC_ARG ApArg; + + Status = AllocateApFuncBufferSingleAP (&ApArg, Mp, ProcessorIndex); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AllocateApFuncBufferSingleAP (&ApArg, Mp, ProcessorIndex); + if (EFI_ERROR (Status)) { + return Status; + } + + Print ( + L"StartupThisAP on Processor %d with %d%s timeout...", + ProcessorIndex, + Timeout, + (Timeout == INFINITE_TIMEOUT) ? L" (infinite)" : L"ms" + ); + Status = Mp->StartupThisAP ( + Mp, + ApFunction, + ProcessorIndex, + NULL, + Timeout * 1000, + &ApArg, + NULL + ); + if (EFI_ERROR (Status)) { + Print (L"failed: %r\n", Status); + return Status; + } else { + Print (L"done.\n"); + Print (ApArg.Buffer[ProcessorIndex]); + } + + FreeApFuncBuffer (&ApArg, ProcessorIndex + 1); + + return EFI_SUCCESS; +} + +/** Runs all APs. + + @param Mp The MP Services Protocol. + @param NumCpus The number of CPUs in the system. + @param Timeout Timeout in milliseconds. + @param RunAPsSequentially Run APs sequentially (FALSE: run simultaneously) + + @return EFI_SUCCESS on success, or an error code. + +**/ +STATIC +EFI_STATUS +StartupAllAPs ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN NumCpus, + IN UINTN Timeout, + IN BOOLEAN RunAPsSequentially + ) +{ + EFI_STATUS Status; + UINTN Index; + APFUNC_ARG ApArg; + + Status = AllocateApFuncBufferAllAPs (&ApArg, Mp, NumCpus); + if (EFI_ERROR (Status)) { + return Status; + } + + Print ( + L"Running with SingleThread %s, %u%s timeout...", + (RunAPsSequentially) ? L"TRUE" : L"FALSE", + Timeout, + (Timeout == INFINITE_TIMEOUT) ? L" (infinite)" : L"ms" + ); + + Status = Mp->StartupAllAPs ( + Mp, + ApFunction, + RunAPsSequentially, + NULL, + Timeout * 1000, + &ApArg, + NULL + ); + + if (EFI_ERROR (Status)) { + Print (L"failed: %r\n", Status); + + return Status; + } else { + Print (L"done.\n"); + + for (Index = 0; Index < NumCpus; Index++) { + Print (ApArg.Buffer[Index]); + } + } + + FreeApFuncBuffer (&ApArg, NumCpus); + return EFI_SUCCESS; +} + +/** + Enables the specified AP. + + @param Mp The MP Services Protocol. + @param ProcessorIndex The processor to enable. + @param ProcessorHealthy The health status of the processor. + + @return EFI_SUCCESS on success, or an error code. +**/ +STATIC +EFI_STATUS +EnableAP ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + UINTN ProcessorIndex, + BOOLEAN ProcessorHealthy + ) +{ + EFI_STATUS Status; + UINT32 HealthFlag; + + if (ProcessorHealthy) { + Print (L"Enabling Processor %d with HealthFlag healthy...", ProcessorIndex); + HealthFlag = PROCESSOR_HEALTH_STATUS_BIT; + } else { + Print (L"Enabling Processor %d with HealthFlag faulted...", ProcessorIndex); + HealthFlag = 0; + } + + Status = Mp->EnableDisableAP (Mp, ProcessorIndex, TRUE, &HealthFlag); + if (EFI_ERROR (Status)) { + Print (L"failed: %r\n", Status); + return Status; + } else { + Print (L"done.\n"); + } + + return Status; +} + +/** + Disables the specified AP. + + @param Mp The MP Services Protocol. + @param ProcessorIndex The processor to disable. + @param ProcessorHealthy The health status of the processor. + + @return EFI_SUCCESS on success, or an error code. +**/ +STATIC +EFI_STATUS +DisableAP ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + UINTN ProcessorIndex, + BOOLEAN ProcessorHealthy + ) +{ + EFI_STATUS Status; + UINT32 HealthFlag; + + if (ProcessorHealthy) { + Print (L"Disabling Processor %d with HealthFlag healthy...", ProcessorIndex); + HealthFlag = PROCESSOR_HEALTH_STATUS_BIT; + } else { + Print (L"Disabling Processor %d with HealthFlag faulted...", ProcessorIndex); + HealthFlag = 0; + } + + Status = Mp->EnableDisableAP (Mp, ProcessorIndex, FALSE, &HealthFlag); + if (EFI_ERROR (Status)) { + Print (L"failed: %r\n", Status); + return Status; + } else { + Print (L"done.\n"); + } + + return Status; +} + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_MP_SERVICES_PROTOCOL *Mp; + UINTN BspIndex; + UINTN CpuIndex; + UINTN NumCpus; + BOOLEAN ProcessorHealthy; + MP_SERVICES_TEST_OPTIONS Options; + + BspIndex = 0; + + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (VOID **)&Mp + ); + if (EFI_ERROR (Status)) { + Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not installed on platform?\n", Status); + return EFI_NOT_FOUND; + } + + Status = ParseArguments (&Options); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + Status = GetProcessorInformation (Mp, &NumCpus, &BspIndex); + if (EFI_ERROR (Status)) { + Print (L"Error: Failed to fetch processor information.\n"); + return Status; + } + + if (Options.PrintBspProcessorIndex) { + Status = Mp->WhoAmI (Mp, &CpuIndex); + if (EFI_ERROR (Status)) { + Print (L"WhoAmI failed: %r\n", Status); + return Status; + } else { + Print (L"BSP: %016lx\n", CpuIndex); + } + } + + if (Options.PrintProcessorInformation) { + NumCpus = PrintProcessorInformation (Mp, &BspIndex); + if (NumCpus < 2) { + Print (L"Error: Uniprocessor system found.\n"); + return EFI_INVALID_PARAMETER; + } + } + + if (Options.RunSingleAP) { + Status = StartupThisAP ( + Mp, + Options.ProcessorIndex, + Options.Timeout + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (Options.RunAllAPs) { + Status = StartupAllAPs (Mp, NumCpus, Options.Timeout, Options.RunAPsSequentially); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (Options.EnableProcessor) { + ProcessorHealthy = TRUE; + if (Options.SetProcessorUnhealthy) { + ProcessorHealthy = FALSE; + } + + Status = EnableAP (Mp, Options.ProcessorIndex, ProcessorHealthy); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (Options.DisableProcessor) { + ProcessorHealthy = TRUE; + if (Options.SetProcessorUnhealthy) { + ProcessorHealthy = FALSE; + } + + Status = DisableAP (Mp, Options.ProcessorIndex, ProcessorHealthy); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Application/MpServicesTest/Options.c b/MdeModulePkg/Application/MpServicesTest/Options.c new file mode 100644 index 000000000000..e820c061e1ec --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/Options.c @@ -0,0 +1,164 @@ +/** @file + Options handling code. + + Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ Copyright (c) 2010-2019 Finnbarr P. Murphy. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include "Options.h" + +STATIC UINTN Argc; +STATIC CHAR16 **Argv; + +/** + + This function provides argc and argv. + + @return Status +**/ +EFI_STATUS +GetArg ( + VOID + ) +{ + EFI_STATUS Status; + EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&ShellParameters + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Argc = ShellParameters->Argc; + Argv = ShellParameters->Argv; + return EFI_SUCCESS; +} + +/** + Print app usage. +**/ +STATIC +VOID +PrintUsage ( + VOID + ) +{ + Print (L"MpServicesTest: usage\n"); + Print (L" MpServicesTest -A [-O]\n"); + Print (L" MpServicesTest -T \n"); + Print (L" MpServicesTest -S \n"); + Print (L" MpServicesTest -P\n"); + Print (L" MpServicesTest -U\n"); + Print (L" MpServicesTest -W\n"); + Print (L" MpServicesTest -E \n"); + Print (L" MpServicesTest -D \n"); + Print (L" MpServicesTest -h\n"); + Print (L"Parameter:\n"); + Print (L" -A: Run all APs.\n"); + Print (L" -O: Run APs sequentially (use with -A).\n"); + Print (L" -T: Specify timeout in milliseconds. Default is to wait forever.\n"); + Print (L" -S: Specify the single AP to run.\n"); + Print (L" -P: Print processor information.\n"); + Print (L" -U: Set the specified AP to the Unhealthy status (use with -E/-D).\n"); + Print (L" -W: Run WhoAmI and print index of BSP.\n"); + Print (L" -E: Enable the specified AP.\n"); + Print (L" -D: Disable the specified AP.\n"); + Print (L" -h: Print this help page.\n"); +} + +/** + Parses any arguments provided on the command line. + + @param Options The arguments structure. + + @return EFI_SUCCESS on success, or an error code. +**/ +EFI_STATUS +ParseArguments ( + MP_SERVICES_TEST_OPTIONS *Options + ) +{ + EFI_STATUS Status; + UINT32 ArgIndex; + CONST CHAR16 *Argument; + BOOLEAN NeedsValue; + UINTN *Value; + + Status = GetArg (); + if (EFI_ERROR (Status)) { + Print (L"Please use the UEFI Shell to run this application!\n", Status); + return Status; + } + + if (Argc == 1) { + PrintUsage (); + } + + ZeroMem (Options, sizeof (MP_SERVICES_TEST_OPTIONS)); + + for (ArgIndex = 1; ArgIndex < Argc; ArgIndex++) { + Argument = Argv[ArgIndex]; + NeedsValue = FALSE; + + if (StrCmp (Argument, L"-A") == 0) { + Options->RunAllAPs = TRUE; + } else if (StrCmp (Argument, L"-O") == 0) { + Options->RunAPsSequentially = TRUE; + } else if (StrCmp (Argument, L"-T") == 0) { + NeedsValue = TRUE; + Value = &Options->Timeout; + } else if (StrCmp (Argument, L"-S") == 0) { + Options->RunSingleAP = TRUE; + NeedsValue = TRUE; + Value = &Options->ProcessorIndex; + } else if (StrCmp (Argument, L"-P") == 0) { + Options->PrintProcessorInformation = TRUE; + } else if (StrCmp (Argument, L"-U") == 0) { + Options->SetProcessorUnhealthy = TRUE; + } else if (StrCmp (Argument, L"-W") == 0) { + Options->PrintBspProcessorIndex = TRUE; + } else if (StrCmp (Argument, L"-E") == 0) { + Options->EnableProcessor = TRUE; + NeedsValue = TRUE; + Value = &Options->ProcessorIndex; + } else if (StrCmp (Argument, L"-D") == 0) { + Options->DisableProcessor = TRUE; + NeedsValue = TRUE; + Value = &Options->ProcessorIndex; + } else { + PrintUsage (); + ZeroMem (Options, sizeof (MP_SERVICES_TEST_OPTIONS)); + return EFI_SUCCESS; + } + + if (NeedsValue) { + if ((ArgIndex + 1) < Argc) { + Status = StrDecimalToUintnS (Argv[ArgIndex + 1], NULL, Value); + if (EFI_ERROR (Status)) { + Print (L"Error: option value must be a positive integer.\n"); + PrintUsage (); + return EFI_INVALID_PARAMETER; + } + + ArgIndex++; + } else { + PrintUsage (); + return EFI_INVALID_PARAMETER; + } + } + } + + return EFI_SUCCESS; +} -- 2.30.2