MdePkg/UefidebugLibConOut: Make it runtime safe

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1416

After ExitBootServices, some pointer would be invalid such as
the Protocol pointer and gST. The function depend on those should
be prevent. So disable the related function while after
ExitBootServices.
Change the gST to a internal one, because there will be a cycle
consume between UefiBootServicesTableLib and DebugLib due to the
library constructors.
Also remove the SMM support for this instance.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Turner <Michael.Turner@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Signed-off-by: Zhichao Gao <zhichao.gao@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Aaron Antone 2019-04-08 11:00:28 +08:00 committed by Liming Gao
parent 2b5778c68b
commit 452702d0bc
3 changed files with 141 additions and 52 deletions

View File

@ -9,7 +9,6 @@
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/BaseLib.h>
@ -27,6 +26,9 @@
//
VA_LIST mVaListNull;
extern BOOLEAN mPostEBS;
extern EFI_SYSTEM_TABLE *mDebugST;
/**
Prints a debug message to the debug output device if the specified error level is enabled.
@ -85,33 +87,35 @@ DebugPrintMarker (
{
CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
//
// If Format is NULL, then ASSERT().
//
ASSERT (Format != NULL);
if (!mPostEBS) {
//
// If Format is NULL, then ASSERT().
//
ASSERT (Format != NULL);
//
// Check driver debug mask value and global mask
//
if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
return;
}
//
// Check driver debug mask value and global mask
//
if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
return;
}
//
// Convert the DEBUG() message to a Unicode String
//
if (BaseListMarker == NULL) {
UnicodeVSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, VaListMarker);
} else {
UnicodeBSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, BaseListMarker);
}
//
// Convert the DEBUG() message to a Unicode String
//
if (BaseListMarker == NULL) {
UnicodeVSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, VaListMarker);
} else {
UnicodeBSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, BaseListMarker);
}
//
// Send the print string to the Console Output device
//
if ((gST != NULL) && (gST->ConOut != NULL)) {
gST->ConOut->OutputString (gST->ConOut, Buffer);
//
// Send the print string to the Console Output device
//
if ((mDebugST != NULL) && (mDebugST->ConOut != NULL)) {
mDebugST->ConOut->OutputString (mDebugST->ConOut, Buffer);
}
}
}
@ -205,33 +209,35 @@ DebugAssert (
{
CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
//
// Generate the ASSERT() message in Unicode format
//
UnicodeSPrintAsciiFormat (
Buffer,
sizeof (Buffer),
"ASSERT [%a] %a(%d): %a\n",
gEfiCallerBaseName,
FileName,
LineNumber,
Description
);
if (!mPostEBS) {
//
// Generate the ASSERT() message in Unicode format
//
UnicodeSPrintAsciiFormat (
Buffer,
sizeof (Buffer),
"ASSERT [%a] %a(%d): %a\n",
gEfiCallerBaseName,
FileName,
LineNumber,
Description
);
//
// Send the print string to the Console Output device
//
if ((gST != NULL) && (gST->ConOut != NULL)) {
gST->ConOut->OutputString (gST->ConOut, Buffer);
}
//
// Send the print string to the Console Output device
//
if ((mDebugST != NULL) && (mDebugST->ConOut != NULL)) {
mDebugST->ConOut->OutputString (mDebugST->ConOut, Buffer);
}
//
// Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
//
if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
CpuBreakpoint ();
} else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
CpuDeadLoop ();
//
// Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
//
if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
CpuBreakpoint ();
} else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
CpuDeadLoop ();
}
}
}

View File

@ -0,0 +1,77 @@
/** @file
UEFI Dxe DebugLib constructor that prevent some debug service after ExitBootServices event,
because some pointer is nulled at that phase.
Copyright (c) 2018, Microsoft Corporation
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
//
// BOOLEAN value to indicate if it is at the post ExitBootServices pahse
//
BOOLEAN mPostEBS = FALSE;
EFI_EVENT mExitBootServicesEvent;
//
// Pointer to SystemTable
// This library instance may have a cycle consume with UefiBootServicesTableLib
// because of the constructors.
//
EFI_SYSTEM_TABLE *mDebugST;
/**
This routine sets the mPostEBS for exit boot servies true
to prevent DebugPort protocol dereferences when the pointer is nulled.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
**/
VOID
EFIAPI
ExitBootServicesCallback (
EFI_EVENT Event,
VOID* Context
)
{
mPostEBS = TRUE;
return;
}
/**
The constructor gets the pointers to the system table.
And create a event to indicate it is after ExitBootServices.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
DxeDebugLibConstructor(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
mDebugST = SystemTable;
SystemTable->BootServices->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
ExitBootServicesCallback,
NULL,
&gEfiEventExitBootServicesGuid,
&mExitBootServicesEvent
);
return EFI_SUCCESS;
}

View File

@ -3,7 +3,9 @@
#
# Debug Lib that sends messages to the Console Output Device in the EFI System Table.
#
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018, Microsoft Corporation
#
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@ -17,8 +19,9 @@
FILE_GUID = 5cddfaf3-e9a7-4d16-bdce-1e002df475bb
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = DxeDebugLibConstructor
#
# VALID_ARCHITECTURES = IA32 X64 EBC
@ -27,6 +30,7 @@
[Sources]
DebugLib.c
DebugLibConstructor.c
@ -39,9 +43,11 @@
BaseLib
PcdLib
PrintLib
UefiBootServicesTableLib
DebugPrintErrorLevelLib
[Guids]
gEfiEventExitBootServicesGuid ## CONSUMES
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES