]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdePkg/UefiDebugLibDebugPortProtocol: Make it runtime safe
authorAaron Antone <aanton@microsoft.com>
Mon, 8 Apr 2019 02:48:00 +0000 (10:48 +0800)
committerLiming Gao <liming.gao@intel.com>
Mon, 22 Apr 2019 01:52:54 +0000 (09:52 +0800)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1416

After ExitBootServices, some pointer would be invalid such as
the Protocol pointer and gBS. The function depend on those should
be prevent. So disable the related function while after
ExitBootServices.
Change the gBS 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>
MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c
MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c [new file with mode: 0644]
MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf

index 24bfb4f37e8e587b227d25cb96821ff8276eddc8..cd7e2abbd3b22c198973cf819fb004b6f944ead7 100644 (file)
@@ -9,7 +9,6 @@
 #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
@@ -37,6 +36,9 @@ EFI_DEBUGPORT_PROTOCOL *mDebugPort = NULL;
 //\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
@@ -56,31 +58,33 @@ UefiDebugLibDebugPortProtocolWrite (
   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
@@ -142,31 +146,33 @@ DebugPrintMarker (
 {\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
@@ -259,31 +265,33 @@ DebugAssert (
 {\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
diff --git a/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c b/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLibConstructor.c
new file mode 100644 (file)
index 0000000..ed2cb70
--- /dev/null
@@ -0,0 +1,77 @@
+/** @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
index d9f4f8a548600c5c43b9b2d83fc76e55de76e523..10a8f2a8576b1df7d8f62b7b161277bb02195bcc 100644 (file)
@@ -3,7 +3,9 @@
 #\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
@@ -17,8 +19,9 @@
   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
@@ -27,6 +30,7 @@
 \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