mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-26 16:47:40 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
383 lines
13 KiB
C
383 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>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#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;
|
|
}
|