[edk2,3/4] MdeModulePkg/DxeRuntimeDebugLibSerialPort: invoke RuntimeDebugOutputProtocol

Message ID 20180301181142.16817-4-ard.biesheuvel@linaro.org
State New
Headers show
Series
  • implement runtime debug output protocl
Related show

Commit Message

Ard Biesheuvel March 1, 2018, 6:11 p.m.
Extend the functionality of DxeRuntimeDebugLibSerialPort by invoking
any available RuntimeDebugOutputProtocol to emit debug output at
runtime rather than staying silent.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c                       | 155 +++++++++++++++++---
 MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf |   5 +
 2 files changed, 143 insertions(+), 17 deletions(-)

-- 
2.11.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c b/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c
index e1266f77fa41..b5460f10ebb6 100644
--- a/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c
+++ b/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c
@@ -25,10 +25,16 @@ 
 #include <Library/PcdLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/SerialPortLib.h>
+#include <Protocol/RuntimeDebugOutput.h>
 
 STATIC EFI_EVENT      mEfiExitBootServicesEvent;
+STATIC EFI_EVENT      mEfiVirtualAddressChangeEvent;
+STATIC EFI_EVENT      mRegisterRuntimeDebugOutputProtocolEvent;
+STATIC VOID           *mRegisterProtocolRegistration;
 STATIC BOOLEAN        mEfiAtRuntime = FALSE;
 
+STATIC EDK2_RUNTIME_DEBUG_OUTPUT_PROTOCOL   *mRuntimeOutput = NULL;
+
 //
 // Define the maximum debug and assert message length that this library supports
 //
@@ -53,6 +59,58 @@  ExitBootServicesEvent (
 }
 
 /**
+  Attach to the RuntimeDebugOutputProtocol as soon as it gets registered
+
+  @param[in]  Event   The Event that is being processed.
+  @param[in]  Context The Event Context.
+
+**/
+STATIC
+VOID
+EFIAPI
+RegisterRuntimeDebugOutputProtocolEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  EFI_STATUS          Status;
+  EFI_BOOT_SERVICES   *BS;
+
+  BS = Context;
+
+  Status = BS->LocateProtocol (&gEdkiiRuntimeDebugOutputProtocolGuid,
+                 mRegisterProtocolRegistration,
+                 (VOID **)&mRuntimeOutput);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  BS->CloseEvent (Event);
+}
+
+/**
+  Fix up virtual address of the runtime debug output protocol
+
+  @param[in]  Event   The Event that is being processed.
+  @param[in]  Context The Event Context.
+
+**/
+STATIC
+VOID
+EFIAPI
+VirtualAddressChangeEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  EFI_RUNTIME_SERVICES  *RT;
+
+  RT = Context;
+
+  RT->ConvertPointer (0x0, (VOID **)&mRuntimeOutput);
+}
+
+/**
   The constructor function to initialize the Serial Port library and
   register a callback for the ExitBootServices event.
 
@@ -70,17 +128,64 @@  DxeRuntimeDebugLibSerialPortConstructor (
   IN EFI_SYSTEM_TABLE  *SystemTable
   )
 {
-  EFI_STATUS    Status;
+  EFI_STATUS          Status;
+  EFI_BOOT_SERVICES   *BS;
 
   Status = SerialPortInitialize ();
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  return SystemTable->BootServices->CreateEventEx (EVT_NOTIFY_SIGNAL,
-                                      TPL_NOTIFY, ExitBootServicesEvent, NULL,
-                                      &gEfiEventExitBootServicesGuid,
-                                      &mEfiExitBootServicesEvent);
+  BS = SystemTable->BootServices;
+
+  Status = BS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                 RegisterRuntimeDebugOutputProtocolEvent, BS,
+                 &mRegisterRuntimeDebugOutputProtocolEvent);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Register for protocol notifications on this event
+  //
+  Status = BS->RegisterProtocolNotify (&gEdkiiRuntimeDebugOutputProtocolGuid,
+                 mRegisterRuntimeDebugOutputProtocolEvent,
+                 &mRegisterProtocolRegistration);
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocolEvent;
+  }
+
+  //
+  // Kick the event so we will perform an initial pass of
+  // current installed drivers
+  //
+  BS->SignalEvent (mRegisterRuntimeDebugOutputProtocolEvent);
+
+  Status = BS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                 ExitBootServicesEvent, NULL,
+                 &gEfiEventExitBootServicesGuid,
+                 &mEfiExitBootServicesEvent);
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocolEvent;
+  }
+
+  Status = BS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
+                 VirtualAddressChangeEvent, SystemTable->RuntimeServices,
+                 &gEfiEventVirtualAddressChangeGuid,
+                 &mEfiVirtualAddressChangeEvent);
+  if (EFI_ERROR (Status)) {
+    goto CloseExitBootServicesEvent;
+  }
+
+  return EFI_SUCCESS;
+
+CloseExitBootServicesEvent:
+  BS->CloseEvent (mEfiExitBootServicesEvent);
+
+CloseProtocolEvent:
+  BS->CloseEvent (mRegisterRuntimeDebugOutputProtocolEvent);
+
+  return Status;
 }
 
 /**
@@ -100,7 +205,29 @@  DxeRuntimeDebugLibSerialPortDestructor (
   IN EFI_SYSTEM_TABLE  *SystemTable
   )
 {
-  return SystemTable->BootServices->CloseEvent (mEfiExitBootServicesEvent);
+  EFI_BOOT_SERVICES   *BS;
+
+  BS = SystemTable->BootServices;
+
+  BS->CloseEvent (mRegisterRuntimeDebugOutputProtocolEvent);
+  BS->CloseEvent (mEfiExitBootServicesEvent);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+UINTN
+DebugWriteOutput (
+  IN  UINT8               *Buffer,
+  IN  UINTN               NumberOfBytes
+  )
+{
+  if (!mEfiAtRuntime) {
+    return SerialPortWrite (Buffer, NumberOfBytes);
+  } else if (mRuntimeOutput != NULL) {
+    return mRuntimeOutput->Write (mRuntimeOutput, Buffer, NumberOfBytes);
+  }
+  return 0;
 }
 
 /**
@@ -129,10 +256,6 @@  DebugPrint (
   CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
   VA_LIST  Marker;
 
-  if (mEfiAtRuntime) {
-    return;
-  }
-
   //
   // If Format is NULL, then ASSERT().
   //
@@ -155,7 +278,7 @@  DebugPrint (
   //
   // Send the print string to a Serial Port
   //
-  SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+  DebugWriteOutput ((UINT8 *)Buffer, AsciiStrLen (Buffer));
 }
 
 
@@ -196,12 +319,10 @@  DebugAssert (
   AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n",
     gEfiCallerBaseName, FileName, LineNumber, Description);
 
-  if (!mEfiAtRuntime) {
-    //
-    // Send the print string to the Console Output device
-    //
-    SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
-  }
+  //
+  // Send the print string to the Console Output device
+  //
+  DebugWriteOutput ((UINT8 *)Buffer, AsciiStrLen (Buffer));
 
   //
   // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
diff --git a/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf b/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
index 813358096982..d2fbdde25f1d 100644
--- a/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
+++ b/MdeModulePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
@@ -36,6 +36,7 @@  [Sources]
   DebugLib.c
 
 [Packages]
+  MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
 
 [LibraryClasses]
@@ -48,6 +49,10 @@  [LibraryClasses]
 
 [Guids]
   gEfiEventExitBootServicesGuid                         ## CONSUMES ## Event
+  gEfiEventVirtualAddressChangeGuid                     ## CONSUMES ## Event
+
+[Protocols]
+  gEdkiiRuntimeDebugOutputProtocolGuid                  ## SOMETIMES_CONSUMES
 
 [Pcd]
   gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue     ## SOMETIMES_CONSUMES