#include <Uefi.h>\r
\r
#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/PrintLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/BaseLib.h>\r
//\r
VA_LIST mVaListNull;\r
\r
+extern BOOLEAN mPostEBS;\r
+extern EFI_BOOT_SERVICES *mDebugBS;\r
+\r
/**\r
Send message to DebugPort Protocol.\r
\r
UINTN Length;\r
EFI_STATUS Status;\r
\r
- //\r
- // If mDebugPort is NULL, initialize first.\r
- //\r
- if (mDebugPort == NULL) {\r
- Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&mDebugPort);\r
- if (EFI_ERROR (Status)) {\r
- return;\r
- }\r
+ if (!mPostEBS) {\r
+ //\r
+ // If mDebugPort is NULL, initialize first.\r
+ //\r
+ if (mDebugPort == NULL) {\r
+ Status = mDebugBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&mDebugPort);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ mDebugPort->Reset (mDebugPort);\r
+ }\r
\r
- mDebugPort->Reset (mDebugPort);\r
- }\r
+ //\r
+ // EFI_DEBUGPORT_PROTOCOL.Write is called until all message is sent.\r
+ //\r
+ while (BufferLength > 0) {\r
+ Length = BufferLength;\r
\r
- //\r
- // EFI_DEBUGPORT_PROTOCOL.Write is called until all message is sent.\r
- //\r
- while (BufferLength > 0) {\r
- Length = BufferLength;\r
+ Status = mDebugPort->Write (mDebugPort, WRITE_TIMEOUT, &Length, (VOID *) Buffer);\r
+ if (EFI_ERROR (Status) || BufferLength < Length) {\r
+ break;\r
+ }\r
\r
- Status = mDebugPort->Write (mDebugPort, WRITE_TIMEOUT, &Length, (VOID *) Buffer);\r
- if (EFI_ERROR (Status) || BufferLength < Length) {\r
- break;\r
+ Buffer += Length;\r
+ BufferLength -= Length;\r
}\r
-\r
- Buffer += Length;\r
- BufferLength -= Length;\r
}\r
}\r
\r
{\r
CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
\r
- //\r
- // If Format is NULL, then ASSERT().\r
- //\r
- ASSERT (Format != NULL);\r
+ if (!mPostEBS) {\r
+ //\r
+ // If Format is NULL, then ASSERT().\r
+ //\r
+ ASSERT (Format != NULL);\r
+\r
+ //\r
+ // Check driver debug mask value and global mask\r
+ //\r
+ if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {\r
+ return;\r
+ }\r
\r
- //\r
- // Check driver debug mask value and global mask\r
- //\r
- if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {\r
- return;\r
- }\r
+ //\r
+ // Convert the DEBUG() message to an ASCII String\r
+ //\r
+ if (BaseListMarker == NULL) {\r
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);\r
+ } else {\r
+ AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);\r
+ }\r
\r
- //\r
- // Convert the DEBUG() message to an ASCII String\r
- //\r
- if (BaseListMarker == NULL) {\r
- AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);\r
- } else {\r
- AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);\r
+ //\r
+ // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
+ //\r
+ UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
}\r
-\r
- //\r
- // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
- //\r
- UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
}\r
\r
\r
{\r
CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
\r
- //\r
- // Generate the ASSERT() message in ASCII format\r
- //\r
- AsciiSPrint (\r
- Buffer,\r
- sizeof (Buffer),\r
- "ASSERT [%a] %a(%d): %a\n",\r
- gEfiCallerBaseName,\r
- FileName,\r
- LineNumber,\r
- Description\r
- );\r
-\r
- //\r
- // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
- //\r
- UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
-\r
- //\r
- // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings\r
- //\r
- if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {\r
- CpuBreakpoint ();\r
- } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {\r
- CpuDeadLoop ();\r
+ if (!mPostEBS) {\r
+ //\r
+ // Generate the ASSERT() message in ASCII format\r
+ //\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "ASSERT [%a] %a(%d): %a\n",\r
+ gEfiCallerBaseName,\r
+ FileName,\r
+ LineNumber,\r
+ Description\r
+ );\r
+\r
+ //\r
+ // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
+ //\r
+ UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
+\r
+ //\r
+ // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings\r
+ //\r
+ if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {\r
+ CpuBreakpoint ();\r
+ } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {\r
+ CpuDeadLoop ();\r
+ }\r
}\r
}\r
\r
--- /dev/null
+/** @file\r
+ UEFI Dxe DebugLib constructor that prevent some debug service after ExitBootServices event,\r
+ because some pointer is nulled at that phase.\r
+\r
+ Copyright (c) 2018, Microsoft Corporation\r
+ Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+//\r
+// BOOLEAN value to indicate if it is at the post ExitBootServices pahse\r
+//\r
+BOOLEAN mPostEBS = FALSE;\r
+\r
+EFI_EVENT mExitBootServicesEvent;\r
+\r
+//\r
+// Pointer to SystemTable\r
+// This library instance may have a cycle consume with UefiBootServicesTableLib\r
+// because of the constructors.\r
+//\r
+EFI_BOOT_SERVICES *mDebugBS;\r
+\r
+/**\r
+ This routine sets the mPostEBS for exit boot servies true\r
+ to prevent DebugPort protocol dereferences when the pointer is nulled.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ExitBootServicesCallback (\r
+ EFI_EVENT Event,\r
+ VOID* Context\r
+ )\r
+{\r
+ mPostEBS = TRUE;\r
+ return;\r
+}\r
+\r
+/**\r
+ The constructor gets the pointers to boot services table.\r
+ And create a event to indicate it is after ExitBootServices.\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeDebugLibConstructor(\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ mDebugBS = SystemTable->BootServices;\r
+\r
+ mDebugBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ExitBootServicesCallback,\r
+ NULL,\r
+ &gEfiEventExitBootServicesGuid,\r
+ &mExitBootServicesEvent\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
#\r
# Debug Lib that sends messages to EFI_DEBUGPORT_PROTOCOL.Write.\r
#\r
-# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2018, Microsoft Corporation\r
+#\r
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
FILE_GUID = 102287b4-6b12-4D41-91e1-ebee1f3aa614\r
MODULE_TYPE = UEFI_DRIVER\r
VERSION_STRING = 1.0\r
- LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
+ LIBRARY_CLASS = DebugLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
\r
+ CONSTRUCTOR = DxeDebugLibConstructor\r
\r
#\r
# VALID_ARCHITECTURES = IA32 X64 EBC\r
\r
[Sources]\r
DebugLib.c\r
+ DebugLibConstructor.c\r
\r
\r
\r
BaseLib\r
PcdLib\r
PrintLib\r
- UefiBootServicesTableLib\r
DebugPrintErrorLevelLib\r
\r
+[Guids]\r
+ gEfiEventExitBootServicesGuid ## CONSUMES\r
+\r
[Protocols]\r
gEfiDebugPortProtocolGuid ## CONSUMES\r
\r