From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com []) by mx.groups.io with SMTP id smtpd.web10.2401.1573615709373949821 for ; Tue, 12 Nov 2019 19:29:41 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: michael.a.kubacki@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Nov 2019 19:29:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,299,1569308400"; d="scan'208";a="379091084" Received: from makuback-desk1.amr.corp.intel.com ([10.7.159.162]) by orsmga005.jf.intel.com with ESMTP; 12 Nov 2019 19:29:41 -0800 From: "Kubacki, Michael A" To: devel@edk2.groups.io Cc: Eric Dong , Liming Gao Subject: [edk2-platforms][PATCH V1 23/49] Features/Intel/AcpiDebugFeaturePkg: Add initial package Date: Tue, 12 Nov 2019 19:27:49 -0800 Message-Id: <20191113032816.4056-24-michael.a.kubacki@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20191113032816.4056-1-michael.a.kubacki@intel.com> References: <20191113032816.4056-1-michael.a.kubacki@intel.com> 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/AcpiDebugDxeSmm/AcpiDebugSmm.inf | 58 +++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c | 519 ++++++++++++++++++++ Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.asl | 102 ++++ Features/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md | 121 +++++ 10 files changed, 1068 insertions(+) diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec new file mode 100644 index 0000000000..a74ee3e084 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec @@ -0,0 +1,39 @@ +## @file +# This package provides advanced feature functionality for ACPI Debug support. +# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg. +# +# The DEC files are used by the utilities that parse DSC and +# INF files to generate AutoGen.c and AutoGen.h files +# for the build infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010017 + PACKAGE_NAME = AcpiDebugFeaturePkg + PACKAGE_GUID = 53E3E908-5DF9-4137-ABB9-6DE162C3898F + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[LibraryClasses] + +[Guids] + gAcpiDebugFeaturePkgTokenSpaceGuid = {0xaf2582c0, 0x93fe, 0x466d, {0xb6, 0xa4, 0x4d, 0x23, 0x77, 0xf7, 0x82, 0xa7}} + +[PcdsFeatureFlag] + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugFeatureEnable|FALSE|BOOLEAN|0xA0000001 + +[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx] + ## This PCD specifies the ACPI debug message buffer size. + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugBufferSize|0x10000|UINT32|0xF0000001 + +[PcdsDynamic, PcdsDynamicEx] + ## This PCD specifies ACPI debug message buffer address. + # The PCD value will be updated during boot time when the buffer is allocated. + gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugAddress|0|UINT32|0xD0000001 diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dsc b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dsc new file mode 100644 index 0000000000..62cc559d8f --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dsc @@ -0,0 +1,30 @@ +## @file +# This package provides advanced feature functionality for ACPI Debug support. +# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg. +# +# The DEC files are used by the utilities that parse DSC and +# INF files to generate AutoGen.c and AutoGen.h files +# for the build infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = AcpiDebugFeaturePkg + PLATFORM_GUID = F3001DF1-4A5B-42A9-944B-E766BDDC7B99 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME) + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + PEI_ARCH = IA32 + DXE_ARCH = X64 + +# +# This package always builds the feature. +# +!include Include/AcpiDebugFeature.dsc diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc new file mode 100644 index 0000000000..3e6b1f69c2 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.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 this feature. +# +# The DEC files are used by the utilities that parse DSC and +# INF files to generate AutoGen.c and AutoGen.h files +# for the build infrastructure. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[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 feature. +# +################################################################################ +[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/UefiBootServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + +[LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.DXE_RUNTIME_DRIVER] + ####################################### + # Edk2 Packages + ####################################### + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_SMM_DRIVER] + ####################################### + # Edk2 Packages + ####################################### + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + +################################################################################ +# +# Component section - list of all components that need built for this feature. +# +# Note: The EDK II DSC file is not used to specify how compiled binary images get placed +# into firmware volume images. This section is just a list of modules 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 PI specification. +# There may also be modules listed in this section that are not required in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be +# generated for it, but the binary will not be put into any firmware volume. +# +################################################################################ +# +# Feature PEI Components +# + +# @todo: Change below line to [Components.$(PEI_ARCH)] after https://bugzilla.tianocore.org/show_bug.cgi?id=2308 +# is completed. +[Components.IA32] + ##################################### + # ACPI Debug Feature Package + ##################################### + + # Add library instances here that are not included in package 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://bugzilla.tianocore.org/show_bug.cgi?id=2308 +# is completed. +[Components.X64] + ##################################### + # ACPI Debug Feature Package + ##################################### + + # Add library instances here that are not included in package 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 process. They can be +# applied for any modules or only those modules with the specific +# module style (EDK or EDKII) specified in [Components] section. +# +# For advanced features, it is recommended to enable [BuildOptions] in +# the applicable INF file so it does not affect the whole board package +# build when this DSC file is active. +# +################################################################################################### +[BuildOptions] diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf new file mode 100644 index 0000000000..ae90238bed --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf @@ -0,0 +1,11 @@ +## @file +# FDF file for post-memory ACPI Debug advanced feature modules. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# 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/PreMemory.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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf new file mode 100644 index 0000000000..dfcee0a842 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf @@ -0,0 +1,55 @@ +### @file +# Component description file for the ACPI Debug DXE module. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiDebugDxe + FILE_GUID = EC98FF95-242C-4513-B1BC-69FA24111C58 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeAcpiDebugDxe +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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/AcpiDebugDxeSmm/AcpiDebugSmm.inf new file mode 100644 index 0000000000..089bb57707 --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf @@ -0,0 +1,58 @@ +### @file +# Component description file for Acpi Debug SMM module. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiDebugSmm + FILE_GUID = 9069C144-0A7E-41EF-9C07-418BCA9BF939 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = InitializeAcpiDebugSmm +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = 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 version + +[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/AcpiDebug.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]=0x08:NameOp. + UINT32 NameString; // Byte [4:1]=Name of object. + UINT8 DWordPrefix; // Byte [5]=0x0C: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 out + 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 = 0; +ACPI_DEBUG_HEAD *mAcpiDebug = NULL; + +EFI_SMM_SYSTEM_TABLE2 *mSmst = 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 head. + @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 = 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 here so load the table. + // + ASSERT (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId == 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 patched. + // + UpdateCounter = 1; + for (CurrPtr = (UINT8 *) TableHeader; CurrPtr <= ((UINT8 *) TableHeader + TableHeader->Length) && UpdateCounter < 4; CurrPtr++) { + Signature = (UINT32 *) (CurrPtr + 1); + // + // patch DPTR (address of Acpi debug memory buffer) + // + if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('D', 'P', 'T', 'R')) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + NamePtr->Value = (UINT32) (UINTN) AcpiDebugAddress; + UpdateCounter++; + } + // + // patch EPTR (end of Acpi debug memory buffer) + // + if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('E', 'P', 'T', 'R')) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + NamePtr->Value = BufferEnd; + UpdateCounter++; + } + // + // patch CPTR (used as an index that starts after the Acpi Debug head) + // + if ((*CurrPtr == AML_NAME_OP) && *Signature == SIGNATURE_32 ('C', 'P', 'T', 'R')) { + NamePtr = (NAME_LAYOUT *) CurrPtr; + NamePtr->Value = BufferIndex; + UpdateCounter++; + } + } + + // + // Add the table + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + goto Done; + } + + TableKey = 0; + Status = 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 = 0; + *BufferSize = 0; + + // + // Reserve memory to store Acpi Debug data. + // + AcpiDebugAddress = 0xFFFFFFFF; + PagesNum = EFI_SIZE_TO_PAGES (PcdGet32 (PcdAcpiDebugBufferSize)); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + PagesNum, + &AcpiDebugAddress + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return 0; + } + + DEBUG ((DEBUG_INFO, "AcpiDebugAddress - 0x%08x\n", AcpiDebugAddress)); + + Status = PcdSet32S (PcdAcpiDebugAddress, (UINT32) AcpiDebugAddress); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + gBS->FreePages (AcpiDebugAddress, PagesNum); + return 0; + } + + *BufferSize = PcdGet32 (PcdAcpiDebugBufferSize); + + return AcpiDebugAddress; +} + +/** + Acpi Debug EndOfDxe notification. + + @param[in] Event Event whose notification function is being invoked. + @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 = (ACPI_DEBUG_HEAD *) (UINTN) AllocateAcpiDebugMemory (&BufferSize); + if (mAcpiDebug != 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 DEBUG". + // + CopyMem ((VOID *) mAcpiDebug, ACPI_DEBUG_STR, sizeof (ACPI_DEBUG_STR) - 1); + + BufferIndex = (UINT32) (UINTN) mAcpiDebug; + mBufferEnd = BufferIndex + BufferSize; + + // + // Leave the Index after the Acpi Debug head. + // + BufferIndex += AD_SIZE; + + // + // Patch and Load the SSDT ACPI Tables. + // + PatchAndLoadAcpiTable (mAcpiDebug, BufferIndex, mBufferEnd); + + mAcpiDebug->Head = BufferIndex; + mAcpiDebug->Tail = BufferIndex; + mAcpiDebug->BufferSize = 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 image. + @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 = 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 handler 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 environment into an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled successfully. + +**/ +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 != (mBufferEnd - (UINT32) (UINTN) mAcpiDebug)) || + (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 >= (UINT32) ((UINTN) 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 == '\0') && (mAcpiDebug->Head < mAcpiDebug->Tail)) { + mAcpiDebug->Head ++; + } + + if (mAcpiDebug->Head < mAcpiDebug->Tail) { + 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) mAcpiDebug->Truncate ? "..." : "")); + mAcpiDebug->Head += MAX_BUFFER_SIZE; + + if (mAcpiDebug->Head >= (mAcpiDebug->Tail)) { + // + // When head == tail, we do nothing in handler. + // + mAcpiDebug->Head = mAcpiDebug->Tail; + } + } + } else if ((BOOLEAN) mAcpiDebug->Wrap && ((mAcpiDebug->Head > mAcpiDebug->Tail) + && (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)))){ + // + // If curent ----- buffer + 020 + // ... Tail + // ... Vacant for ASL input + // ... Head + // ... Data for SMM print + // ----- buffer end + // + while ((*(CHAR8 *) (UINTN) mAcpiDebug->Head == '\0') && (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize))) { + mAcpiDebug->Head ++; + } + if (mAcpiDebug->Head < (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)){ + 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) mAcpiDebug->Truncate ? "..." : "")); + mAcpiDebug->Head += MAX_BUFFER_SIZE; + + if (mAcpiDebug->Head >= (UINT32) ((UINTN) mAcpiDebug + mAcpiDebug->BufferSize)) { + // + // We met end of buffer. + // + mAcpiDebug->Wrap = 0; + mAcpiDebug->Head = (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 != NULL) { + // + // Get the Sw dispatch protocol and register SMI callback function. + // + SwDispatch = NULL; + Status = mSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **) &SwDispatch); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + SwContext.SwSmiInputValue = (UINTN) -1; + Status = SwDispatch->Register (SwDispatch, AcpiDebugSmmCallback, &SwContext, &SwHandle); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + mAcpiDebug->SmiTrigger = (UINT8) SwContext.SwSmiInputValue; + mAcpiDebug->SmmVersion = 1; + } + + return EFI_SUCCESS; +} + +/** + Initialize ACPI Debug. + + @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 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 = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **) &SmmBase2); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SmmBase2->InSmm (SmmBase2, &InSmm); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (InSmm); + + if (!InSmm) { + return EFI_UNSUPPORTED; + } + + Status = 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 = NULL; + Status = 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/AcpiDebugDxeSmm/AcpiDebug.asl new file mode 100644 index 0000000000..3504c2d6ea --- /dev/null +++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.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 the buffer(starts after the Acpi Debug head), fixed up during POST + + // + // Use a Mutex to prevent multiple calls from simutaneously writing to 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 DPTR + 0x20, + // if there's SMM handler to print, then it's the starting of the info hasn't been printed yet. + ACTP, 32, // 4 bytes is current tail pointer, is the same as 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 can check for Mutex acquired + If (LEqual (Local0, Zero)) // check for Mutex acquired + { + OperationRegion (ABLK, SystemMemory, CPTR, 32) // Operation region 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 String + Store (0, TRUN) + If (LGreaterEqual (SizeOf (Local1), 32)) + { + Store (1, TRUN) // the input from ASL >= 32 + } + Mid (Local1, 0, 31, AAAA) // extract the input to current buffer + + Add (CPTR, 32, CPTR) // advance current pointer to next string location in memory buffer + If (LGreaterEqual (CPTR, EPTR) ) // check for end of 64kb Acpi debug buffer + { + Add (DPTR, 32, CPTR) // wrap around to beginning of buffer if the 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 acquired + } + + } // End Scope +} // End SSDT diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Readme.md b/Features/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 kernel debugger such as WinDBG. + +**_DO NOT_** use this feature in a production system. It may not handle 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 buffer 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 message output port. + +The DXE driver is required and the SMM driver is optional. The SMM driver eases retrieval of the ACPI debug messages +from a message ring buffer in memory by sending the messages over the SMM debug mechanism. ASL code writes messages up +to 32 characters in length (shorter strings will be padded with zeroes and longer strings will be truncated) to an +ASL debug method. + +## Firmware Volumes +* FvAdvancedPostMemory + +## Modules +* AcpiDebugDxe +* AcpiDebugSmm + +## AcpiDebugDxe +The entry point registers an end of DXE notification. Further action is deferred until end of DXE to allow the +feature PCDs to be customized at boot time in DXE if desired. The notification handler allocates a `EfiReservedMemoryType` +buffer (memory not available to the operating system) of the size specified in `PcdAcpiDebugBufferSize`. The actual +buffer size is allocated on a page boundary of size `EFI_PAGE_SIZE`. The allocated buffer address is written out +as a debug message `AcpiDebugAddress - 0xXXXXXXXX`. In addition, the address is written to `PcdAcpiDebugAddress` +and the actual allocation size is written to `PcdAcpiDebugBufferSize`. + +To expose the ACPI debug buffer to ASL code, an ACPI debug SSDT (defined in `AcpiDebug.asl`) is installed. The pointer +fields in the 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 deferred until end of DXE to allow the +feature PCDs to be customized at boot time if desired. The notification handler registers a SW SMI that can be +triggered in ACPI debug SSDT to invoke the SMI handler `AcpiDebugSmmCallback ()`. The SMI handler retrieves the debug +message from 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 write + to the ACPI memory debug buffer. If AcpiDebugSmm is used, an SMI will + be used to send the message as a DEBUG message. + + It is recommended to instrument the ASL code with a method called `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 allows the `ADBG` references to remain in the ASL code even if + the ACPI debug advanced feature is disabled. Below is a code snippet with 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 require non-standard tool configuration. If the +standard flow in the feature 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 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 integrator can reference to ensure the feature is +functional on their board. + +## Feature Enabling Checklist +*_TODO_* +An ordered list of required activities to achieve desired functionality for 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 should be left empty. -- 2.16.2.windows.1