diff --git a/MdeModulePkg/Include/Guid/DebugMask.h b/MdeModulePkg/Include/Guid/DebugMask.h new file mode 100644 index 0000000000..cfb0a69372 --- /dev/null +++ b/MdeModulePkg/Include/Guid/DebugMask.h @@ -0,0 +1,73 @@ +/** @file + + Debug Mask Protocol. + +Copyright (c) 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEBUG_MASK_H__ +#define __DEBUG_MASK_H__ + +/// +/// Protocol GUID for DXE Phase Debug Mask support +/// +#define EFI_DEBUG_MASK_PROTOCOL_GUID \ + { 0x4c8a2451, 0xc207, 0x405b, {0x96, 0x94, 0x99, 0xea, 0x13, 0x25, 0x13, 0x41} } + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_DEBUG_MASK_PROTOCOL EFI_DEBUG_MASK_PROTOCOL; + +/// +/// +/// +#define EFI_DEBUG_MASK_REVISION 0x00010000 + +// +// DebugMask member functions definition +// +typedef +EFI_STATUS +(EFIAPI * EFI_GET_DEBUG_MASK) ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN OUT UINTN *CurrentDebugMask + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_DEBUG_MASK) ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN UINTN NewDebugMask + ); + +/// +/// DebugMask protocol definition +/// +struct _EFI_DEBUG_MASK_PROTOCOL { + INT64 Revision; + EFI_GET_DEBUG_MASK GetDebugMask; + EFI_SET_DEBUG_MASK SetDebugMask; +}; + +extern EFI_GUID gEfiDebugMaskProtocolGuid; + +/// +/// GUID used to store the global debug mask in an the "EFIDebug" EFI Variabe +/// +#define EFI_GENERIC_VARIABLE_GUID \ + { 0x59d1c24f, 0x50f1, 0x401a, {0xb1, 0x01, 0xf3, 0x3e, 0x0d, 0xae, 0xd4, 0x43} } + +#define DEBUG_MASK_VARIABLE_NAME L"EFIDebug" + +extern EFI_GUID gEfiGenericVariableGuid; + +#endif diff --git a/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.c b/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.c new file mode 100644 index 0000000000..195432ddfd --- /dev/null +++ b/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.c @@ -0,0 +1,341 @@ +/** @file + Debug Print Error Level library instance that provide compatibility with the + "err" shell command. This includes support for the Debug Mask Protocol + supports for global debug print error level mask stored in an EFI Variable. + This library instance only support DXE Phase modules. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include + +/// +/// Debug Mask Protocol function prototypes +/// +EFI_STATUS +EFIAPI +GetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN OUT UINTN *CurrentDebugMask + ); + +EFI_STATUS +EFIAPI +SetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN UINTN NewDebugMask + ); + +/// +/// Debug Mask Protocol instance +/// +EFI_DEBUG_MASK_PROTOCOL mDebugMaskProtocol = { + EFI_DEBUG_MASK_REVISION, + GetDebugMask, + SetDebugMask +}; + +/// +/// Global variable that is set to TRUE after the first attempt is made to +/// retrieve the global error level mask through the EFI Varibale Services. +/// This variable prevents the EFI Variable Services from being called fort +/// every DEBUG() macro. +/// +BOOLEAN mGlobalErrorLevelInitialized = FALSE; + +/// +/// Global variable that contains the current debug error level mask for the +/// module that is using this library instance. This variable is initially +/// set to the PcdDebugPrintErrorLevel value. If the EFI Variable exists that +/// contains the global debug print error level mask, then that override the +/// PcdDebugPrintErrorLevel value. If the Debug Mask Protocol SetDebugMask() +/// service is called, then that overrides bit the PcdDebugPrintErrorLevel and +/// the EFI Variable setting. +/// +UINT32 mDebugPrintErrorLevel = 0; + +/// +/// Global variable that is used to cache a pointer to the EFI System Table +/// that is required to access the EFI Variable Services to get and set +/// the global debug print error level mask value. The UefiBootServicesTableLib +/// is not used to prevent a circular dependency between these libraries. +/// +EFI_SYSTEM_TABLE *mST = NULL; + +/** + The constructor function caches the PCI Express Base Address and creates a + Set Virtual Address Map event to convert physical address to virtual addresses. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor completed successfully. + @retval Other value The constructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeDebugPrintErrorLevelLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initialize the error level mask from PCD setting. + // + mDebugPrintErrorLevel = PcdGet32 (PcdDebugPrintErrorLevel); + + // + // Install Debug Mask Protocol onto ImageHandle + // + mST = SystemTable; + Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDebugMaskProtocolGuid, &mDebugMaskProtocol, + NULL + ); + + // + // Attempt to retrieve the global debug print error level mask from the EFI Variable + // If the EFI Variable can not be accessed when this module's library constructors are + // executed, then the EFI Variable access will be reattempted on every DEBUG() print + // from this module until the EFI Variable services are available. + // + GetDebugPrintErrorLevel (); + + return Status; +} + +/** + The destructor function frees any allocated buffers and closes the Set Virtual + Address Map event. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +DxeDebugPrintErrorLevelLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Uninstall the Debug Mask Protocol from ImageHandle + // + return SystemTable->BootServices->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDebugMaskProtocolGuid, &mDebugMaskProtocol, + NULL + ); +} + +/** + Returns the debug print error level mask for the current module. + + @return Debug print error level mask for the current module. + +**/ +UINT32 +EFIAPI +GetDebugPrintErrorLevel ( + VOID + ) +{ + EFI_STATUS Status; + EFI_TPL CurrentTpl; + UINTN Size; + UINTN GlobalErrorLevel; + + // + // If the constructor has not been executed yet, then just return the PCD value. + // This case should only occur if debug print is generated by a library + // constructor for this module + // + if (mST == NULL) { + return PcdGet32 (PcdDebugPrintErrorLevel); + } + + // + // Check to see if an attempt has been mde to retrieve the global debug print + // error level mask. Since this libtrary instance stores the global debug print + // error level mask in an EFI Variable, the EFI Variable should only be accessed + // once to reduce the overhead of reading the EFI Variable on every debug print + // + if (!mGlobalErrorLevelInitialized) { + // + // Make sure the TPL Level is low enough for EFI Variable Services to be called + // + CurrentTpl = mST->BootServices->RaiseTPL (TPL_HIGH_LEVEL); + mST->BootServices->RestoreTPL (CurrentTpl); + if (CurrentTpl <= TPL_CALLBACK) { + // + // Attempt to retrieve the global debug print error level mask from the + // EFI Variable + // + Size = sizeof (GlobalErrorLevel); + Status = mST->RuntimeServices->GetVariable ( + DEBUG_MASK_VARIABLE_NAME, + &gEfiGenericVariableGuid, + NULL, + &Size, + &GlobalErrorLevel + ); + if (Status != EFI_NOT_AVAILABLE_YET) { + // + // If EFI Variable Services are available, then set a flag so the EFI + // Variable will not be read again by this module. + // + mGlobalErrorLevelInitialized = TRUE; + if (!EFI_ERROR (Status)) { + // + // If the EFI Varible exists, then set this module's module's mask to + // the global debug print error level mask value. + // + mDebugPrintErrorLevel = (UINT32)GlobalErrorLevel; + } + } + } + } + + // + // Return the current mask value for this module. + // + return mDebugPrintErrorLevel; +} + +/** + Sets the global debug print error level mask fpr the entire platform. + + @retval TRUE The debug print error level mask was sucessfully set. + @retval FALSE The debug print error level mask could not be set. + +**/ +BOOLEAN +EFIAPI +SetDebugPrintErrorLevel ( + UINT32 ErrorLevel + ) +{ + EFI_STATUS Status; + EFI_TPL CurrentTpl; + UINTN Size; + UINTN GlobalErrorLevel; + + // + // Make sure the constructor has been executed + // + if (mST != NULL) { + // + // Make sure the TPL Level is low enough for EFI Variable Services + // + CurrentTpl = mST->BootServices->RaiseTPL (TPL_HIGH_LEVEL); + mST->BootServices->RestoreTPL (CurrentTpl); + if (CurrentTpl <= TPL_CALLBACK) { + // + // Attempt to store the global debug print error level mask in an EFI Variable + // + GlobalErrorLevel = (UINTN)ErrorLevel; + Size = sizeof (GlobalErrorLevel); + Status = mST->RuntimeServices->SetVariable ( + DEBUG_MASK_VARIABLE_NAME, + &gEfiGenericVariableGuid, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS), + Size, + &GlobalErrorLevel + ); + if (!EFI_ERROR (Status)) { + // + // If the EFI Variable was updated, then update the mask value for this + // module and return TRUE. + // + mGlobalErrorLevelInitialized = TRUE; + mDebugPrintErrorLevel = ErrorLevel; + return TRUE; + } + } + } + // + // Return FALSE since the EFI Variable could not be updated. + // + return FALSE; +} + +/** + Retrieves the current debug print error level mask for a module are returns + it in CurrentDebugMask. + + @param This The protocol instance pointer. + @param CurrentDebugMask Pointer to the debug print error level mask that + is returned. + + @retval EFI_SUCCESS The current debug print error level mask was + returned in CurrentDebugMask. + @retval EFI_INVALID_PARAMETER CurrentDebugMask is NULL. + @retval EFI_DEVICE_ERROR The current debug print error level mask could + not be retrieved. + +**/ +EFI_STATUS +EFIAPI +GetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN OUT UINTN *CurrentDebugMask + ) +{ + if (CurrentDebugMask == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the current debug mask from mDebugPrintErrorLevel + // + *CurrentDebugMask = (UINTN)mDebugPrintErrorLevel; + return EFI_SUCCESS; +} + +/** + Sets the current debug print error level mask for a module to the value + specified by NewDebugMask. + + @param This The protocol instance pointer. + @param NewDebugMask The new debug print error level mask for this module. + + @retval EFI_SUCCESS The current debug print error level mask was + set to the value specified by NewDebugMask. + @retval EFI_DEVICE_ERROR The current debug print error level mask could + not be set to the value specified by NewDebugMask. + +**/ +EFI_STATUS +EFIAPI +SetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, + IN UINTN NewDebugMask + ) +{ + // + // Store the new debug mask into mDebugPrintErrorLevel + // + mDebugPrintErrorLevel = (UINT32)NewDebugMask; + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf b/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf new file mode 100644 index 0000000000..a4a44b1c2e --- /dev/null +++ b/MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf @@ -0,0 +1,50 @@ +## @file +# Debug Print Error Level library instance that provide compatibility with the +# "err" shell command. This includes support for the Debug Mask Protocol +# supports for global debug print error level mask stored in an EFI Variable. +# This library instance only support DXE Phase modules. +# +# Copyright (c) 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeDebugPrintErrorLevelLib + FILE_GUID = 1D564EC9-9373-49a4-9E3F-E4D7B9974C84 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugPrintErrorLevelLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = DxeDebugPrintErrorLevelLibConstructor + DESTRUCTOR = DxeDebugPrintErrorLevelLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DxeDebugPrintErrorLevelLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PcdLib + +[Protocols] + gEfiDebugMaskProtocolGuid + +[Guids] + gEfiGenericVariableGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 045fd4152a..ae0836a223 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -162,6 +162,10 @@ # Include/Guid/LoadModuleAtFixedAddress.h gLoadFixedAddressConfigurationTableGuid = { 0x2CA88B53,0xD296,0x4080, { 0xA4,0xA5,0xCA,0xD9,0xBA,0xE2,0x4B,0x9 } } + ## GUID used to store the global debug mask value into an EFI Variable + # Include/Guid/DebugMask.h + gEfiGenericVariableGuid = { 0x59d1c24f, 0x50f1, 0x401a, {0xb1, 0x01, 0xf3, 0x3e, 0x0d, 0xae, 0xd4, 0x43} } + [Protocols] ## Load File protocol provides capability to load and unload EFI image into memory and execute it. # Include/Protocol/LoadPe32Image.h @@ -204,6 +208,9 @@ # Include/Protocol/SmmFirmwareVolumeBlock.h gEfiSmmFirmwareVolumeBlockProtocolGuid = { 0xd326d041, 0xbd31, 0x4c01, { 0xb5, 0xa8, 0x62, 0x8b, 0xe8, 0x7f, 0x6, 0x53 }} + ## This protocol allows the error level mask for DEBUG() macros to be adjusted for DXE Phase modules + # Include/Guid/DebugMask.h + gEfiDebugMaskProtocolGuid = { 0x4c8a2451, 0xc207, 0x405b, {0x96, 0x94, 0x99, 0xea, 0x13, 0x25, 0x13, 0x41} } [PcdsFeatureFlag] ## Indicate whether platform can support update capsule across a system reset gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE|BOOLEAN|0x0001001d diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 89cf09e2c5..820b0b7ba2 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -80,6 +80,7 @@ # Misc # DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf @@ -132,13 +133,13 @@ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf -[LibraryClasses.ARM] - # - # It is not possible to prevent the ARM compiler for generic intrinsic functions. - # This library provides the instrinsic functions generate by a given compiler. - # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. - # - NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf +[LibraryClasses.ARM] + # + # It is not possible to prevent the ARM compiler for generic intrinsic functions. + # This library provides the instrinsic functions generate by a given compiler. + # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. + # + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf [PcdsFeatureFlag]