From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web11.650.1573861785938133356 for ; Fri, 15 Nov 2019 15:49:46 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.24, mailfrom: nathaniel.l.desimone@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Nov 2019 15:49:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,310,1569308400"; d="scan'208";a="405499331" Received: from orsmsx110.amr.corp.intel.com ([10.22.240.8]) by fmsmga005.fm.intel.com with ESMTP; 15 Nov 2019 15:49:45 -0800 Received: from orsmsx115.amr.corp.intel.com (10.22.240.11) by ORSMSX110.amr.corp.intel.com (10.22.240.8) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 15 Nov 2019 15:49:44 -0800 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.67]) by ORSMSX115.amr.corp.intel.com ([169.254.4.121]) with mapi id 14.03.0439.000; Fri, 15 Nov 2019 15:49:44 -0800 From: "Nate DeSimone" To: "devel@edk2.groups.io" , "Kubacki, Michael A" CC: "Dong, Eric" , "Gao, Liming" Subject: Re: [edk2-devel] [edk2-platforms][PATCH V1 23/49] Features/Intel/AcpiDebugFeaturePkg: Add initial package Thread-Topic: [edk2-devel] [edk2-platforms][PATCH V1 23/49] Features/Intel/AcpiDebugFeaturePkg: Add initial package Thread-Index: AQHVmdKcPoZAn4Ogk0OyZSvsr65JeKeMqymw Date: Fri, 15 Nov 2019 23:49:44 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AB5BDB277@ORSMSX114.amr.corp.intel.com> References: <20191113032816.4056-1-michael.a.kubacki@intel.com> <20191113032816.4056-24-michael.a.kubacki@intel.com> In-Reply-To: <20191113032816.4056-24-michael.a.kubacki@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiZmUzNTYxOWMtN2FlOC00YWM2LWEyNWEtMzIyZjMxZDczNDk4IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiakhzVmtzVWdueHRuYUhXZzlBdEJlTVwvTlJzODRuUVZnQkpEdlhtNlFoY1g2N1Y0RFFNODJLWkN0Qkp5czhnQUcifQ== x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.140] MIME-Version: 1.0 Return-Path: nathaniel.l.desimone@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone -----Original Message----- From: devel@edk2.groups.io On Behalf Of Kubacki, Mi= chael A Sent: Tuesday, November 12, 2019 7:28 PM To: devel@edk2.groups.io Cc: Dong, Eric ; Gao, Liming Subject: [edk2-devel] [edk2-platforms][PATCH V1 23/49] Features/Intel/Acpi= DebugFeaturePkg: Add initial package Adds a new feature package for the ACPI Debug feature. Cc: Eric Dong Cc: Liming Gao Signed-off-by: Michael Kubacki --- Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec = | 39 ++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dsc = | 30 ++ Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc= | 125 +++++ Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf = | 11 + Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PreMemory.fdf = | 8 + Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe= .inf | 55 +++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSm= m/AcpiDebugSmm.inf | 58 +++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c = | 519 ++++++++++++++++++++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.as= l | 102 ++++ Features/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md = | 121 +++++ 10 files changed, 1068 insertions(+) diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeature= Pkg.dec b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.= dec new file mode 100644 index 0000000000..a74ee3e084 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.d +++ ec @@ -0,0 +1,39 @@ +## @file +# This package provides advanced feature functionality for ACPI Debug sup= port. +# This package should only depend on EDK II Core packages, IntelSiliconPk= g, and MinPlatformPkg. +# +# The DEC files are used by the utilities that parse DSC and # INF=20 +files to generate AutoGen.c and AutoGen.h files # for the build=20 +infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ## + +[Defines] + DEC_SPECIFICATION =3D 0x00010017 + PACKAGE_NAME =3D AcpiDebugFeaturePkg + PACKAGE_GUID =3D 53E3E908-5DF9-4137-ABB9-6DE162C3898F + PACKAGE_VERSION =3D 0.1 + +[Includes] + Include + +[LibraryClasses] + +[Guids] + gAcpiDebugFeaturePkgTokenSpaceGuid =3D {0xaf2582c0, 0x93fe, 0x466d,= =20 +{0xb6, 0xa4, 0x4d, 0x23, 0x77, 0xf7, 0x82, 0xa7}} + +[PcdsFeatureFlag] + +gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugFeatureEnable|FALSE|BOOL +EAN|0xA0000001 + +[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx] + ## This PCD specifies the ACPI debug message buffer size. + +gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugBufferSize|0x10000|UINT3 +2|0xF0000001 + +[PcdsDynamic, PcdsDynamicEx] + ## This PCD specifies ACPI debug message buffer address. + # The PCD value will be updated during boot time when the buffer is al= located. + +gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugAddress|0|UINT32|0xD0000 +001 diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeature= Pkg.dsc b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.= dsc new file mode 100644 index 0000000000..62cc559d8f --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.d +++ sc @@ -0,0 +1,30 @@ +## @file +# This package provides advanced feature functionality for ACPI Debug sup= port. +# This package should only depend on EDK II Core packages, IntelSiliconPk= g, and MinPlatformPkg. +# +# The DEC files are used by the utilities that parse DSC and # INF=20 +files to generate AutoGen.c and AutoGen.h files # for the build=20 +infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ## + +[Defines] + PLATFORM_NAME =3D AcpiDebugFeaturePkg + PLATFORM_GUID =3D F3001DF1-4A5B-42A9-944B-E766BDDC7B99 + PLATFORM_VERSION =3D 0.1 + DSC_SPECIFICATION =3D 0x00010005 + OUTPUT_DIRECTORY =3D Build/$(PLATFORM_NAME) + SUPPORTED_ARCHITECTURES =3D IA32|X64 + BUILD_TARGETS =3D DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER =3D DEFAULT + PEI_ARCH =3D IA32 + DXE_ARCH =3D X64 + +# +# This package always builds the feature. +# +!include Include/AcpiDebugFeature.dsc diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebu= gFeature.dsc b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDeb= ugFeature.dsc new file mode 100644 index 0000000000..3e6b1f69c2 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeat +++ ure.dsc @@ -0,0 +1,125 @@ +## @file +# This is a build description file for the ACPI Debug advanced feature. +# This file should be included into another package DSC file to build thi= s feature. +# +# The DEC files are used by the utilities that parse DSC and # INF=20 +files to generate AutoGen.c and AutoGen.h files # for the build=20 +infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ## + +####################################################################### +######### +# +# Defines Section - statements that will be processed to create a Makefil= e. +# +####################################################################### +######### +[Defines] +!ifndef $(PEI_ARCH) + !error "PEI_ARCH must be specified to build this feature!" +!endif +!ifndef $(DXE_ARCH) + !error "DXE_ARCH must be specified to build this feature!" +!endif + +####################################################################### +######### +# +# Library Class section - list of all Library Classes needed by this feat= ure. +# +####################################################################### +######### +[LibraryClasses] + ####################################### + # Edk2 Packages + ####################################### + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + +UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBo +otServicesTableLib.inf + +UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntr +yPoint.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + +UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/ +UefiRuntimeServicesTableLib.inf + +[LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.DXE_RUNTIME_DRI +VER] + ####################################### + # Edk2 Packages + ####################################### + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + +MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAl +locationLib.inf + +[LibraryClasses.common.DXE_SMM_DRIVER] + ####################################### + # Edk2 Packages + ####################################### + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + +MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllo +cationLib.inf + +SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTable +Lib.inf + +####################################################################### +######### +# +# Component section - list of all components that need built for this fea= ture. +# +# Note: The EDK II DSC file is not used to specify how compiled binary im= ages get placed +# into firmware volume images. This section is just a list of modul= es to compile from +# source into UEFI-compliant binaries. +# It is the FDF file that contains information on combining binary = files into firmware +# volume images, whose concept is beyond UEFI and is described in P= I specification. +# There may also be modules listed in this section that are not req= uired in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-co= mpliant binary will be +# generated for it, but the binary will not be put into any firmwar= e volume. +# +####################################################################### +######### +# +# Feature PEI Components +# + +# @todo: Change below line to [Components.$(PEI_ARCH)] after https://bugz= illa.tianocore.org/show_bug.cgi?id=3D2308 +# is completed. +[Components.IA32] + ##################################### + # ACPI Debug Feature Package + ##################################### + + # Add library instances here that are not included in package=20 + components and should be tested # in the package build. + + # Add components here that should be included in the package build. + +# +# Feature DXE Components +# + +# @todo: Change below line to [Components.$(DXE_ARCH)] after https://bugz= illa.tianocore.org/show_bug.cgi?id=3D2308 +# is completed. +[Components.X64] + ##################################### + # ACPI Debug Feature Package + ##################################### + + # Add library instances here that are not included in package=20 + components and should be tested # in the package build. + + # Add components here that should be included in the package build. + Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf + Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf + +####################################################################### +############################ +# +# BuildOptions Section - Define the module specific tool chain flags that= should be used as +# the default flags for a module. These flags are = appended to any +# standard flags that are defined by the build pro= cess. They can be +# applied for any modules or only those modules wi= th the specific +# module style (EDK or EDKII) specified in [Compon= ents] section. +# +# For advanced features, it is recommended to enab= le [BuildOptions] in +# the applicable INF file so it does not affect th= e whole board package +# build when this DSC file is active. +# +####################################################################### +############################ +[BuildOptions] diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemo= ry.fdf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fd= f new file mode 100644 index 0000000000..ae90238bed --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fd +++ f @@ -0,0 +1,11 @@ +## @file +# FDF file for post-memory ACPI Debug advanced feature modules. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ## + + INF Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf + INF Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PreMemor= y.fdf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PreMemory.fdf new file mode 100644 index 0000000000..3100daee71 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PreMemory.fdf @@ -0,0 +1,8 @@ +## @file +# FDF file for pre-memory ACPI Debug advanced feature modules. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ## diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/= AcpiDebugDxe.inf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDx= eSmm/AcpiDebugDxe.inf new file mode 100644 index 0000000000..dfcee0a842 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiD +++ ebugDxe.inf @@ -0,0 +1,55 @@ +### @file +# Component description file for the ACPI Debug DXE module. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ### + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D AcpiDebugDxe + FILE_GUID =3D EC98FF95-242C-4513-B1BC-69FA24111C58 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeAcpiDebugDxe +# +# The following information is for reference only and not required by the= build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + PcdLib + DxeServicesLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec + +[Pcd] + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugBufferSize ## CONSUMES + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugAddress ## PRODUCES + +[Sources] + AcpiDebug.c + AcpiDebug.asl + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + gEfiSmmBase2ProtocolGuid ## CONSUMES # only for SMM version + gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES # only for SMM version + gEfiSmmEndOfDxeProtocolGuid ## NOTIFY # only for SMM version + +[Guids] + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + +[Depex] + gEfiAcpiTableProtocolGuid diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/= AcpiDebugSmm.inf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDx= eSmm/AcpiDebugSmm.inf new file mode 100644 index 0000000000..089bb57707 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiD +++ ebugSmm.inf @@ -0,0 +1,58 @@ +### @file +# Component description file for Acpi Debug SMM module. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# #=20 +SPDX-License-Identifier: BSD-2-Clause-Patent # ### + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D AcpiDebugSmm + FILE_GUID =3D 9069C144-0A7E-41EF-9C07-418BCA9BF939 + MODULE_TYPE =3D DXE_SMM_DRIVER + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x0001000A + ENTRY_POINT =3D InitializeAcpiDebugSmm +# +# The following information is for reference only and not required by the= build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + PcdLib + DxeServicesLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec + +[Pcd] + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugBufferSize ## CONSUMES + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugAddress ## PRODUCES + +[Sources] + AcpiDebug.c + AcpiDebug.asl + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + gEfiSmmBase2ProtocolGuid ## CONSUMES + gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## NOTIFY + +[Guids] + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event # only for DXE v= ersion + +[Depex] + gEfiAcpiTableProtocolGuid AND + gEfiSmmBase2ProtocolGuid AND + gEfiSmmSwDispatch2ProtocolGuid diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/= AcpiDebug.c b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/= AcpiDebug.c new file mode 100644 index 0000000000..42428d8005 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiD +++ ebug.c @@ -0,0 +1,519 @@ +/** @file + ACPI Debug feature driver implementation. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ACPI_DEBUG_STR "INTEL ACPI DEBUG" + +// +// ASL NAME structure +// +#pragma pack(1) +typedef struct { + UINT8 NameOp; // Byte [0]=3D0x08:NameOp. + UINT32 NameString; // Byte [4:1]=3DName of object. + UINT8 DWordPrefix; // Byte [5]=3D0x0C:DWord Prefix. + UINT32 Value; // 0 ; Value of named object. +} NAME_LAYOUT; +#pragma pack() + +#pragma pack(1) +typedef struct { + UINT8 Signature[16]; // "INTEL ACPI DEBUG" + UINT32 BufferSize; // Total size of Acpi Debug buffer including = header structure + UINT32 Head; // Current buffer pointer for SMM to print ou= t + UINT32 Tail; // Current buffer pointer for ASL to input + UINT8 SmiTrigger; // Value to trigger the SMI via B2 port + UINT8 Wrap; // If current Tail < Head + UINT8 SmmVersion; // If SMM version + UINT8 Truncate; // If the input from ASL > MAX_BUFFER_SIZE +} ACPI_DEBUG_HEAD; +#pragma pack() + +#define AD_SIZE sizeof (ACPI_DEBUG_HEAD) // This is 0x20 + +#define MAX_BUFFER_SIZE 32 + +UINT32 mBufferEnd =3D 0; +ACPI_DEBUG_HEAD *mAcpiDebug =3D NULL; + +EFI_SMM_SYSTEM_TABLE2 *mSmst =3D NULL; + +/** + Patch and load ACPI table. + + @param[in] AcpiDebugAddress Address of Acpi debug memory buffer. + @param[in] BufferIndex Index that starts after the Acpi Debug he= ad. + @param[in] BufferEnd End of Acpi debug memory buffer. + +**/ +VOID +PatchAndLoadAcpiTable ( + IN ACPI_DEBUG_HEAD *AcpiDebugAddress, + IN UINT32 BufferIndex, + IN UINT32 BufferEnd + ) +{ + EFI_STATUS Status; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + UINTN Size; + EFI_ACPI_DESCRIPTION_HEADER *TableHeader; + UINTN TableKey; + UINT8 *CurrPtr; + UINT32 *Signature; + NAME_LAYOUT *NamePtr; + UINT8 UpdateCounter; + + Status =3D GetSectionFromFv ( + &gEfiCallerIdGuid, + EFI_SECTION_RAW, + 0, + (VOID **) &TableHeader, + &Size + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return; + } + + // + // This is Acpi Debug SSDT. Acpi Debug should be enabled if we reach he= re so load the table. + // + ASSERT (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId =3D= =3D=20 + SIGNATURE_64 ('A', 'D', 'e', 'b', 'T', 'a', 'b', 'l')); + + // + // Patch some pointers for the ASL code before loading the SSDT. + // + + // + // Count pointer updates, so we can stop after all three pointers are p= atched. + // + UpdateCounter =3D 1; + for (CurrPtr =3D (UINT8 *) TableHeader; CurrPtr <=3D ((UINT8 *) TableHe= ader + TableHeader->Length) && UpdateCounter < 4; CurrPtr++) { + Signature =3D (UINT32 *) (CurrPtr + 1); + // + // patch DPTR (address of Acpi debug memory buffer) + // + if ((*CurrPtr =3D=3D AML_NAME_OP) && *Signature =3D=3D SIGNATURE_32 (= 'D', 'P', 'T', 'R')) { + NamePtr =3D (NAME_LAYOUT *) CurrPtr; + NamePtr->Value =3D (UINT32) (UINTN) AcpiDebugAddress; + UpdateCounter++; + } + // + // patch EPTR (end of Acpi debug memory buffer) + // + if ((*CurrPtr =3D=3D AML_NAME_OP) && *Signature =3D=3D SIGNATURE_32 (= 'E', 'P', 'T', 'R')) { + NamePtr =3D (NAME_LAYOUT *) CurrPtr; + NamePtr->Value =3D BufferEnd; + UpdateCounter++; + } + // + // patch CPTR (used as an index that starts after the Acpi Debug head= ) + // + if ((*CurrPtr =3D=3D AML_NAME_OP) && *Signature =3D=3D SIGNATURE_32 (= 'C', 'P', 'T', 'R')) { + NamePtr =3D (NAME_LAYOUT *) CurrPtr; + NamePtr->Value =3D BufferIndex; + UpdateCounter++; + } + } + + // + // Add the table + // + Status =3D gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID= = =20 + **)&AcpiTable); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { + goto Done; + } + + TableKey =3D 0; + Status =3D AcpiTable->InstallAcpiTable ( + AcpiTable, + TableHeader, + Size, + &TableKey + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + goto Done; + } + +Done: + gBS->FreePool (TableHeader); + return ; +} + +/** + Allocate Acpi Debug memory. + + @param[out] BufferSize Pointer to Acpi debug memory buffer size. + + @return Address of Acpi debug memory buffer. + +**/ +EFI_PHYSICAL_ADDRESS +AllocateAcpiDebugMemory ( + OUT UINT32 *BufferSize + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS AcpiDebugAddress; + UINTN PagesNum; + + AcpiDebugAddress =3D 0; + *BufferSize =3D 0; + + // + // Reserve memory to store Acpi Debug data. + // + AcpiDebugAddress =3D 0xFFFFFFFF; + PagesNum =3D EFI_SIZE_TO_PAGES (PcdGet32 (PcdAcpiDebugBufferSize)); + Status =3D gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + PagesNum, + &AcpiDebugAddress + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return 0; + } + + DEBUG ((DEBUG_INFO, "AcpiDebugAddress - 0x%08x\n",=20 + AcpiDebugAddress)); + + Status =3D PcdSet32S (PcdAcpiDebugAddress, (UINT32) AcpiDebugAddress); = + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + gBS->FreePages (AcpiDebugAddress, PagesNum); + return 0; + } + + *BufferSize =3D PcdGet32 (PcdAcpiDebugBufferSize); + + return AcpiDebugAddress; +} + +/** + Acpi Debug EndOfDxe notification. + + @param[in] Event Event whose notification function is being invoke= d. + @param[in] Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +AcpiDebugEndOfDxeNotification ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 BufferSize; + UINT32 BufferIndex; + + mAcpiDebug =3D (ACPI_DEBUG_HEAD *) (UINTN) AllocateAcpiDebugMemory=20 + (&BufferSize); if (mAcpiDebug !=3D NULL) { + // + // Init ACPI DEBUG buffer to lower case 'x'. + // + SetMem ((VOID *) mAcpiDebug, BufferSize, 0x78); + + // + // Clear header of AD_SIZE bytes. + // + ZeroMem ((VOID *) mAcpiDebug, AD_SIZE); + + // + // Write a signature to the first line of the buffer, "INTEL ACPI DEB= UG". + // + CopyMem ((VOID *) mAcpiDebug, ACPI_DEBUG_STR, sizeof=20 + (ACPI_DEBUG_STR) - 1); + + BufferIndex =3D (UINT32) (UINTN) mAcpiDebug; + mBufferEnd =3D BufferIndex + BufferSize; + + // + // Leave the Index after the Acpi Debug head. + // + BufferIndex +=3D AD_SIZE; + + // + // Patch and Load the SSDT ACPI Tables. + // + PatchAndLoadAcpiTable (mAcpiDebug, BufferIndex, mBufferEnd); + + mAcpiDebug->Head =3D BufferIndex; + mAcpiDebug->Tail =3D BufferIndex; + mAcpiDebug->BufferSize =3D BufferSize; } + + // + // Close event, so it will not be invoked again. + // + gBS->CloseEvent (Event); + + return ; +} + +/** + Initialize ACPI Debug. + + @param[in] ImageHandle The firmware allocated handle for the EFI ima= ge. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The driver initializes correctly. + +**/ +EFI_STATUS +EFIAPI +InitializeAcpiDebugDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT EndOfDxeEvent; + + // + // Register EndOfDxe notification + // that point could ensure the Acpi Debug related PCDs initialized. + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AcpiDebugEndOfDxeNotification, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Software SMI callback for ACPI Debug which is called from ACPI method. + + @param[in] DispatchHandle The unique handle assigned to this ha= ndler by SmiHandlerRegister(). + @param[in] Context Points to an optional handler context= which was specified when the + handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in = memory that will + be conveyed from a non-SMM environmen= t into an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled successfull= y. + +**/ +EFI_STATUS +EFIAPI +AcpiDebugSmmCallback ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommBufferSize + ) +{ + UINT8 Buffer[MAX_BUFFER_SIZE]; + + // + // Validate the fields in mAcpiDebug to ensure there is no harm to SMI = handler. + // mAcpiDebug is below 4GB and the start address of whole buffer. + // + if ((mAcpiDebug->BufferSize !=3D (mBufferEnd - (UINT32) (UINTN) mAcpiDe= bug)) || + (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + AD_SIZE)) || + (mAcpiDebug->Head > mBufferEnd) || + (mAcpiDebug->Tail < (UINT32) ((UINTN) mAcpiDebug + AD_SIZE)) || + (mAcpiDebug->Tail > mBufferEnd)) { + // + // If some fields in mAcpiDebug are invaid, return directly. + // + return EFI_SUCCESS; + } + + if (!(BOOLEAN)mAcpiDebug->Wrap && ((mAcpiDebug->Head >=3D (UINT32) ((UI= NTN) mAcpiDebug + AD_SIZE)) + && (mAcpiDebug->Head < mAcpiDebug->Tail))){ + // + // If curent ----- buffer + 020 + // ... + // ... Head + // ... Data for SMM print + // ... Tail + // ... Vacant for ASL input + // ----- buffer end + // + // skip NULL block + // + while ((*(CHAR8 *) (UINTN) mAcpiDebug->Head =3D=3D '\0') && (mAcpiDeb= ug->Head < mAcpiDebug->Tail)) { + mAcpiDebug->Head ++; + } + + if (mAcpiDebug->Head < mAcpiDebug->Tail) { + ZeroMem (Buffer, MAX_BUFFER_SIZE); + AsciiStrnCpyS ((CHAR8 *) Buffer, MAX_BUFFER_SIZE, (CHAR8 *)=20 + (UINTN) mAcpiDebug->Head, MAX_BUFFER_SIZE - 1); + + DEBUG ((DEBUG_INFO | DEBUG_ERROR, "%a%a\n", Buffer, (BOOLEAN) mAcpi= Debug->Truncate ? "..." : "")); + mAcpiDebug->Head +=3D MAX_BUFFER_SIZE; + + if (mAcpiDebug->Head >=3D (mAcpiDebug->Tail)) { + // + // When head =3D=3D tail, we do nothing in handler. + // + mAcpiDebug->Head =3D mAcpiDebug->Tail; + } + } + } else if ((BOOLEAN) mAcpiDebug->Wrap && ((mAcpiDebug->Head > mAcpiDebu= g->Tail) + && (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->Buf= ferSize)))){ + // + // If curent ----- buffer + 020 + // ... Tail + // ... Vacant for ASL input + // ... Head + // ... Data for SMM print + // ----- buffer end + // + while ((*(CHAR8 *) (UINTN) mAcpiDebug->Head =3D=3D '\0') && (mAcpiDeb= ug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize))) { + mAcpiDebug->Head ++; + } + if (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->Buf= ferSize)){ + ZeroMem (Buffer, MAX_BUFFER_SIZE); + AsciiStrnCpyS ((CHAR8 *) Buffer, MAX_BUFFER_SIZE, (CHAR8 *) (UINTN)= mAcpiDebug->Head, MAX_BUFFER_SIZE - 1); + DEBUG ((DEBUG_INFO | DEBUG_ERROR, "%a%a\n", Buffer, (BOOLEAN) mAcpi= Debug->Truncate ? "..." : "")); + mAcpiDebug->Head +=3D MAX_BUFFER_SIZE; + + if (mAcpiDebug->Head >=3D (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug= ->BufferSize)) { + // + // We met end of buffer. + // + mAcpiDebug->Wrap =3D 0; + mAcpiDebug->Head =3D (UINT32) ((UINTN) mAcpiDebug + AD_SIZE); + } + } + } + + return EFI_SUCCESS; +} + +/** + Acpi Debug SmmEndOfDxe notification. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. + + **/ +EFI_STATUS +EFIAPI +AcpiDebugSmmEndOfDxeNotification ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch; + EFI_SMM_SW_REGISTER_CONTEXT SwContext; + EFI_HANDLE SwHandle; + + AcpiDebugEndOfDxeNotification (NULL, NULL); + + if (mAcpiDebug !=3D NULL) { + // + // Get the Sw dispatch protocol and register SMI callback function. + // + SwDispatch =3D NULL; + Status =3D mSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid,= NULL, (VOID **) &SwDispatch); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + SwContext.SwSmiInputValue =3D (UINTN) -1; + Status =3D SwDispatch->Register (SwDispatch, AcpiDebugSmmCallback, &S= wContext, &SwHandle); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + mAcpiDebug->SmiTrigger =3D (UINT8) SwContext.SwSmiInputValue; + mAcpiDebug->SmmVersion =3D 1; + } + + return EFI_SUCCESS; +} + +/** + Initialize ACPI Debug. + + @param[in] ImageHandle The firmware allocated handle for the EFI ima= ge. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The driver initializes correctly. + +**/ +EFI_STATUS +EFIAPI +InitializeAcpiDebugSmm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *Registration; + EFI_SMM_BASE2_PROTOCOL *SmmBase2; + BOOLEAN InSmm; + + Status =3D gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID= =20 + **) &SmmBase2); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D SmmBase2->InSmm (SmmBase2, &InSmm); ASSERT_EFI_ERROR=20 + (Status); if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (InSmm); + + if (!InSmm) { + return EFI_UNSUPPORTED; + } + + Status =3D SmmBase2->GetSmstLocation (SmmBase2, &mSmst); + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { + return Status; + } + + // + // Register SmmEndOfDxe notification + // that point could ensure the Acpi Debug related PCDs initialized. + // + Registration =3D NULL; + Status =3D mSmst->SmmRegisterProtocolNotify ( + &gEfiSmmEndOfDxeProtocolGuid, + AcpiDebugSmmEndOfDxeNotification, + &Registration + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/= AcpiDebug.asl b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSm= m/AcpiDebug.asl new file mode 100644 index 0000000000..3504c2d6ea --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiD +++ ebug.asl @@ -0,0 +1,102 @@ +/** @file + SSDT for the ACPI Debug feature. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +DefinitionBlock ( + "AcpiDebug.aml", + "SSDT", + 2, + "Intel ", + "ADebTabl", + 0x1000 + ) +{ + Scope(\) + { + // + // These pointers are patched during POST. + // + Name (DPTR, 0x80000000) // Address of Acpi debug memory buffer, fixed= up during POST + Name (EPTR, 0x80000000) // End of Acpi debug memory buffer, fixed up = during POST + Name (CPTR, 0x80000000) // Current pointer used as an index into=20 +the buffer(starts after the Acpi Debug head), fixed up during POST + + // + // Use a Mutex to prevent multiple calls from simutaneously writing t= o the same memory. + // + Mutex (MMUT, 0) + + // + // Operational region for SMI port access + // + OperationRegion (ADBP, SystemIO, 0xB2, 2) + Field (ADBP, ByteAcc, NoLock, Preserve) + { + B2PT, 8, + B3PT, 8, + } + + // + // Write a string to a memory buffer + // + Method (MDBG, 1, Serialized) + { + OperationRegion (ADHD, SystemMemory, DPTR, 32) // Operation region = for Acpi Debug buffer first 0x20 bytes + Field (ADHD, ByteAcc, NoLock, Preserve) + { + Offset (0x0), + ASIG, 128, // 16 bytes is Signature + Offset (0x10), + ASIZ, 32, // 4 bytes is buffer size + ACHP, 32, // 4 bytes is current head pointer, normally is D= PTR + 0x20, + // if there's SMM handler to print, then it's t= he starting of the info hasn't been printed yet. + ACTP, 32, // 4 bytes is current tail pointer, is the same a= s CPTR + SMIN, 8, // 1 byte of SMI Number for trigger callback + WRAP, 8, // 1 byte of wrap status + SMMV, 8, // 1 byte of SMM version status + TRUN, 8 // 1 byte of truncate status + } + + Store (Acquire (MMUT, 1000), Local0) // save Acquire result so we c= an check for Mutex acquired + If (LEqual (Local0, Zero)) // check for Mutex acquired + { + OperationRegion (ABLK, SystemMemory, CPTR, 32) // Operation regio= n to allow writes to ACPI debug buffer + Field (ABLK, ByteAcc, NoLock, Preserve) + { + Offset (0x0), + AAAA, 256 // 32 bytes is max size for string or data + } + ToHexString (Arg0, Local1) // convert argument to Hexadecimal Str= ing + Store (0, TRUN) + If (LGreaterEqual (SizeOf (Local1), 32)) + { + Store (1, TRUN) // the input from ASL >=3D 32 + } + Mid (Local1, 0, 31, AAAA) // extract the input to current=20 + buffer + + Add (CPTR, 32, CPTR) // advance current pointer to next string lo= cation in memory buffer + If (LGreaterEqual (CPTR, EPTR) ) // check for end of 64kb Acpi de= bug buffer + { + Add (DPTR, 32, CPTR) // wrap around to beginning of buffer if t= he end has been reached + Store (1, WRAP) + } + Store (CPTR, ACTP) + + If (SMMV) + { + // + // Trigger the SMI to print + // + Store (SMIN, B2PT) + } + Release (MMUT) + } + + Return (Local0) // return error code indicating whether Mutex was a= cquired + } + + } // End Scope +} // End SSDT diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md b/Feat= ures/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md new file mode 100644 index 0000000000..bc0dce9348 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md @@ -0,0 +1,121 @@ +# Overview +* **Feature Name:** ACPI Debug +* **PI Phase(s) Supported:** DXE and SMM +* **SMM Required?** No + +## Purpose +This feature is an alternative ACPI debug mechanism to port 0x80 or a ker= nel debugger such as WinDBG. + +**_DO NOT_** use this feature in a production system. It may not handle= =20 +SMM memory buffers or data input/output from SMM in a safe manner. + +# High-Level Theory of Operation +There are two driver modes: + 1. DXE - ACPI debug messages should be manually read from a memory buff= er on the target machine using a utility + that has the ability to read main memory. + 2. SMM - ACPI debug messages should be read from the firmware debug mes= sage output port. + +The DXE driver is required and the SMM driver is optional. The SMM=20 +driver eases retrieval of the ACPI debug messages from a message ring=20 +buffer in memory by sending the messages over the SMM debug mechanism.=20 +ASL code writes messages up to 32 characters in length (shorter strings w= ill be padded with zeroes and longer strings will be truncated) to an ASL d= ebug method. + +## Firmware Volumes +* FvAdvancedPostMemory + +## Modules +* AcpiDebugDxe +* AcpiDebugSmm + +## AcpiDebugDxe +The entry point registers an end of DXE notification. Further action is= =20 +deferred until end of DXE to allow the feature PCDs to be customized at= =20 +boot time in DXE if desired. The notification handler allocates a=20 +`EfiReservedMemoryType` buffer (memory not available to the operating=20 +system) of the size specified in `PcdAcpiDebugBufferSize`. The actual=20 +buffer size is allocated on a page boundary of size `EFI_PAGE_SIZE`. The = allocated buffer address is written out as a debug message `AcpiDebugAddres= s - 0xXXXXXXXX`. In addition, the address is written to `PcdAcpiDebugAddres= s` and the actual allocation size is written to `PcdAcpiDebugBufferSize`. + +To expose the ACPI debug buffer to ASL code, an ACPI debug SSDT=20 +(defined in `AcpiDebug.asl`) is installed. The pointer fields in the=20 +SSDT are patched by `AcpiDebugDxe` to the actual buffer address. The SSDT= is installed using the `EFI_ACPI_TABLE_PROTOCOL`. + +## AcpiDebugSmm +The entry point registers an end of DXE notification. Further action is= =20 +deferred until end of DXE to allow the feature PCDs to be customized at= =20 +boot time if desired. The notification handler registers a SW SMI that=20 +can be triggered in ACPI debug SSDT to invoke the SMI handler=20 +`AcpiDebugSmmCallback ()`. The SMI handler retrieves the debug message fr= om the buffer at `PcdAcpiDebugAddress` and sends it to the `DEBUG` function= for the given SMM `DebugLib` instance assigned to `AcpiDebugSmm`. + +## Key Functions +* `MDBG` _(ASL method)_ + + This method is given a single argument with a number or string to=20 + write to the ACPI memory debug buffer. If AcpiDebugSmm is used, an=20 + SMI will be used to send the message as a DEBUG message. + + It is recommended to instrument the ASL code with a method called=20 + `ADBG`. An ASL caller sends a debug message as follows: + + ``` + ADBG("This is a test.") + ADBG(Arg0) + ``` + +* `ADBG` _(ASL method)_ is intended to be a wrapper of `MDBG` that=20 +allows the `ADBG` references to remain in the ASL code even if + the ACPI debug advanced feature is disabled. Below is a code snippet wi= th a sample implementation for `ADBG`. + + ``` + External (MDBG, MethodObj) + Method (ADBG, 1, Serialized) + { + If (CondRefOf (MDBG)) // Check if ACPI Debug SSDT is loaded + { + Return (MDBG (Arg0)) + } + Return (0) + } + ``` + +## Configuration +* PcdAcpiDebugEnable - Enables this feature. +* PcdAcpiDebugAddress - The address of the ACPI debug message buffer. +* PcdAcpiDebugBufferSize - The size of the ACPI debug message buffer. + +## Data Flows +*_TODO_* +Architecturally defined data structures and flows for the feature. + +## Control Flows +*_TODO_* +Key control flows for the feature. + +## Build Flows +*_TODO_* +Any special build flows should be described in this section. + +This is particularly useful for features that use custom build tools or= =20 +require non-standard tool configuration. If the standard flow in the feat= ure package template is used, this section may be empty. + +## Test Point Results +*_TODO_* +The test(s) that can verify porting is complete for the feature. + +Each feature must describe at least one test point to verify the=20 +feature is successful. If the test point is not implemented, this should = be stated. + +## Functional Exit Criteria +*_TODO_* +The testable functionality for the feature. + +This section should provide an ordered list of criteria that a board=20 +integrator can reference to ensure the feature is functional on their boa= rd. + +## Feature Enabling Checklist +*_TODO_* +An ordered list of required activities to achieve desired functionality f= or the feature. + +## Common Optimizations +*_TODO_* +Common size or performance tuning options for this feature. + +This section is recommended but not required. If not used, the contents s= hould be left empty. -- 2.16.2.windows.1