@@ -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
@@ -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
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