mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 13:35:48 +01:00 
			
		
		
		
	1. Do not use tab characters 2. No trailing white space in one line 3. All files must end with CRLF Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			389 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			389 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  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 <PiDxe.h>
 | 
						|
 | 
						|
#include <Library/DebugPrintErrorLevelLib.h>
 | 
						|
#include <Library/PcdLib.h>
 | 
						|
#include <Library/HobLib.h>
 | 
						|
 | 
						|
#include <Guid/DebugMask.h>
 | 
						|
 | 
						|
///
 | 
						|
/// Debug Mask Protocol function prototypes
 | 
						|
///
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
///
 | 
						|
/// 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 overrides the
 | 
						|
/// PcdDebugPrintErrorLevel value. The EFI Variable can optionally be
 | 
						|
/// discovered via a HOB so early DXE drivers can access the variable. If the
 | 
						|
/// Debug Mask Protocol SetDebugMask() service is called, then that overrides
 | 
						|
/// 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  *mSystemTable                         = 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
 | 
						|
  //
 | 
						|
  mSystemTable = 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 a HOB can be used to set the global debug print error level. If no value
 | 
						|
  // was found 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;
 | 
						|
  VOID        *Hob;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 (mSystemTable == NULL) {
 | 
						|
    return PcdGet32 (PcdDebugPrintErrorLevel);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check to see if an attempt has been made to retrieve the global debug print
 | 
						|
  // error level mask.  Since this library 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 = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
 | 
						|
    mSystemTable->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 = mSystemTable->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;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // If variable services are not yet available optionally get the global
 | 
						|
        // debug print error level mask from a HOB.
 | 
						|
        //
 | 
						|
        Hob = GetFirstGuidHob (&gEfiGenericVariableGuid);
 | 
						|
        if (Hob != NULL) {
 | 
						|
          if (GET_GUID_HOB_DATA_SIZE (Hob) == sizeof (UINT32)) {
 | 
						|
            mDebugPrintErrorLevel = *(UINT32 *)GET_GUID_HOB_DATA (Hob);
 | 
						|
            mGlobalErrorLevelInitialized = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Return the current mask value for this module.
 | 
						|
  //
 | 
						|
  return mDebugPrintErrorLevel;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sets the global debug print error level mask fpr the entire platform.
 | 
						|
 | 
						|
  @param   ErrorLevel     Global debug print error level
 | 
						|
 | 
						|
  @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 (mSystemTable != NULL) {
 | 
						|
    //
 | 
						|
    // Make sure the TPL Level is low enough for EFI Variable Services
 | 
						|
    //
 | 
						|
    CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
 | 
						|
    mSystemTable->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 = mSystemTable->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;
 | 
						|
}
 |