summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/ReportStatusCodeRouter
diff options
context:
space:
mode:
authorxli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524>2009-12-16 04:50:57 +0000
committerxli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524>2009-12-16 04:50:57 +0000
commitcfc2ba61e499764a7cfbfef4da37f95bd54c2987 (patch)
tree21b2fae0c93f2efa349b202d102a872af0e8c2ea /MdeModulePkg/Universal/ReportStatusCodeRouter
parent8a1dc102d9c4f208c13913b95c14bcc2e29b6ccf (diff)
downloadedk2-platforms-cfc2ba61e499764a7cfbfef4da37f95bd54c2987.tar.xz
Fix the issue that callback function with TPL lower than TPL_HIGH_LEVEL cannot handle status code at TPL_HIGH_LEVEL.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9568 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/ReportStatusCodeRouter')
-rw-r--r--MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c165
-rw-r--r--MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h20
-rw-r--r--MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf2
3 files changed, 132 insertions, 55 deletions
diff --git a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c
index aa2fa100f0..a8c43a0d62 100644
--- a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c
+++ b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c
@@ -35,6 +35,49 @@ EFI_RSC_HANDLER_PROTOCOL mRscHandlerProtocol = {
};
/**
+ Event callback function to invoke status code handler in list.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context, which is
+ always zero in current implementation.
+
+**/
+VOID
+EFIAPI
+RscHandlerNotification (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
+ EFI_PHYSICAL_ADDRESS Address;
+ RSC_DATA_ENTRY *RscData;
+
+ CallbackEntry = (RSC_HANDLER_CALLBACK_ENTRY *) Context;
+
+ //
+ // Traverse the status code data buffer to parse all
+ // data to report.
+ //
+ Address = CallbackEntry->StatusCodeDataBuffer;
+ while (Address < CallbackEntry->EndPointer) {
+ RscData = (RSC_DATA_ENTRY *) (UINTN) Address;
+ CallbackEntry->RscHandlerCallback (
+ RscData->Type,
+ RscData->Value,
+ RscData->Instance,
+ &RscData->CallerId,
+ &RscData->Data
+ );
+
+ Address += (sizeof (RSC_DATA_ENTRY) + RscData->Data.Size);
+ Address = ALIGN_VARIABLE (Address);
+ }
+
+ CallbackEntry->EndPointer = CallbackEntry->StatusCodeDataBuffer;
+}
+
+/**
Register the callback function for ReportStatusCode() notification.
When this function is called the function pointer is added to an internal list and any future calls to
@@ -69,6 +112,7 @@ Register (
IN EFI_TPL Tpl
)
{
+ EFI_STATUS Status;
LIST_ENTRY *Link;
RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
@@ -86,13 +130,35 @@ Register (
}
}
- CallbackEntry = AllocatePool (sizeof (RSC_HANDLER_CALLBACK_ENTRY));
+ CallbackEntry = AllocateZeroPool (sizeof (RSC_HANDLER_CALLBACK_ENTRY));
ASSERT (CallbackEntry != NULL);
CallbackEntry->Signature = RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE;
CallbackEntry->RscHandlerCallback = Callback;
CallbackEntry->Tpl = Tpl;
+ //
+ // If TPL of registered callback funtion is not TPL_HIGH_LEVEL, then event should be created
+ // for it, and related buffer for status code data should be prepared.
+ // Here the data buffer must be prepared in advance, because Report Status Code Protocol might
+ // be invoked under TPL_HIGH_LEVEL and no memory allocation is allowed then.
+ // If TPL is TPL_HIGH_LEVEL, then all status code will be reported immediately, without data
+ // buffer and event trigger.
+ //
+ if (Tpl != TPL_HIGH_LEVEL) {
+ CallbackEntry->StatusCodeDataBuffer = (EFI_PHYSICAL_ADDRESS) AllocatePool (EFI_PAGE_SIZE);
+ CallbackEntry->BufferSize = EFI_PAGE_SIZE;
+ CallbackEntry->EndPointer = CallbackEntry->StatusCodeDataBuffer;
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ Tpl,
+ RscHandlerNotification,
+ CallbackEntry,
+ &CallbackEntry->Event
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
InsertTailList (&mCallbackListHead, &CallbackEntry->Node);
return EFI_SUCCESS;
@@ -131,6 +197,10 @@ Unregister (
//
// If the function is found in list, delete it and return.
//
+ if (CallbackEntry->Tpl != TPL_HIGH_LEVEL) {
+ FreePool ((VOID *) (UINTN) CallbackEntry->StatusCodeDataBuffer);
+ gBS->CloseEvent (CallbackEntry->Event);
+ }
RemoveEntryList (&CallbackEntry->Node);
FreePool (CallbackEntry);
return EFI_SUCCESS;
@@ -141,34 +211,6 @@ Unregister (
}
/**
- Event callback function to invoke status code handler in list.
-
- @param Event Event whose notification function is being invoked.
- @param Context Pointer to the notification function's context, which is
- always zero in current implementation.
-
-**/
-VOID
-EFIAPI
-RscHandlerNotification (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- RSC_EVENT_CONTEXT *RscContext;
-
- RscContext = (RSC_EVENT_CONTEXT *) Context;
-
- RscContext->RscHandlerCallback (
- RscContext->Type,
- RscContext->Value,
- RscContext->Instance,
- RscContext->CallerId,
- RscContext->Data
- );
-}
-
-/**
Provides an interface that a software module can call to report a status code.
@param Type Indicates the type of status code being reported.
@@ -198,9 +240,9 @@ ReportDispatcher (
{
LIST_ENTRY *Link;
RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
- RSC_EVENT_CONTEXT Context;
- EFI_EVENT Event;
+ RSC_DATA_ENTRY *RscData;
EFI_STATUS Status;
+ VOID *NewBuffer;
//
// Use atom operation to avoid the reentant of report.
@@ -224,26 +266,53 @@ ReportDispatcher (
continue;
}
- Context.RscHandlerCallback = CallbackEntry->RscHandlerCallback;
- Context.Type = Type;
- Context.Value = Value;
- Context.Instance = Instance;
- Context.CallerId = CallerId;
- Context.Data = Data;
+ //
+ // If callback is registered with TPL lower than TPL_HIGH_LEVEL, event must be signaled at boot time to possibly wait for
+ // allowed TPL to report status code. Related data should also be stored in data buffer.
+ //
+ CallbackEntry->EndPointer = ALIGN_VARIABLE (CallbackEntry->EndPointer);
+ RscData = (RSC_DATA_ENTRY *) (UINTN) CallbackEntry->EndPointer;
+ CallbackEntry->EndPointer += sizeof (RSC_DATA_ENTRY);
+ if (Data != NULL) {
+ CallbackEntry->EndPointer += Data->Size;
+ }
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- CallbackEntry->Tpl,
- RscHandlerNotification,
- &Context,
- &Event
- );
- ASSERT_EFI_ERROR (Status);
+ //
+ // If data buffer is about to be used up (7/8 here), try to reallocate a buffer with double size, if not at TPL_HIGH_LEVEL.
+ //
+ if (CallbackEntry->EndPointer > (CallbackEntry->StatusCodeDataBuffer + (CallbackEntry->BufferSize / 8) * 7)) {
+ if (EfiGetCurrentTpl () < TPL_HIGH_LEVEL) {
+ NewBuffer = ReallocatePool (
+ CallbackEntry->BufferSize,
+ CallbackEntry->BufferSize * 2,
+ (VOID *) (UINTN) CallbackEntry->StatusCodeDataBuffer
+ );
+ if (NewBuffer != NULL) {
+ CallbackEntry->EndPointer = (EFI_PHYSICAL_ADDRESS) NewBuffer + (CallbackEntry->EndPointer - CallbackEntry->StatusCodeDataBuffer);
+ CallbackEntry->StatusCodeDataBuffer = (EFI_PHYSICAL_ADDRESS) NewBuffer;
+ CallbackEntry->BufferSize *= 2;
+ }
+ }
+ }
- Status = gBS->SignalEvent (Event);
- ASSERT_EFI_ERROR (Status);
+ //
+ // If data buffer is used up, do not report for this time.
+ //
+ if (CallbackEntry->EndPointer > (CallbackEntry->StatusCodeDataBuffer + CallbackEntry->BufferSize)) {
+ continue;
+ }
+
+ RscData->Type = Type;
+ RscData->Value = Value;
+ RscData->Instance = Instance;
+ if (CallerId != NULL) {
+ CopyGuid (&RscData->CallerId, CallerId);
+ }
+ if (Data != NULL) {
+ CopyMem (&RscData->Data, Data, Data->HeaderSize + Data->Size);
+ }
- Status = gBS->CloseEvent (Event);
+ Status = gBS->SignalEvent (CallbackEntry->Event);
ASSERT_EFI_ERROR (Status);
}
diff --git a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h
index a87ad5fdb8..2b727aba65 100644
--- a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h
+++ b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h
@@ -29,7 +29,9 @@
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
#include <Library/UefiRuntimeLib.h>
+#include "Library/UefiLib.h"
#define RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE SIGNATURE_32 ('r', 'h', 'c', 'e')
@@ -37,17 +39,21 @@ typedef struct {
UINTN Signature;
EFI_RSC_HANDLER_CALLBACK RscHandlerCallback;
EFI_TPL Tpl;
+ EFI_EVENT Event;
+ EFI_PHYSICAL_ADDRESS StatusCodeDataBuffer;
+ UINTN BufferSize;
+ EFI_PHYSICAL_ADDRESS EndPointer;
LIST_ENTRY Node;
} RSC_HANDLER_CALLBACK_ENTRY;
typedef struct {
- EFI_RSC_HANDLER_CALLBACK RscHandlerCallback;
- EFI_STATUS_CODE_TYPE Type;
- EFI_STATUS_CODE_VALUE Value;
- UINT32 Instance;
- EFI_GUID *CallerId;
- EFI_STATUS_CODE_DATA *Data;
-} RSC_EVENT_CONTEXT;
+ EFI_STATUS_CODE_TYPE Type;
+ EFI_STATUS_CODE_VALUE Value;
+ UINT32 Instance;
+ UINT32 Reserved;
+ EFI_GUID CallerId;
+ EFI_STATUS_CODE_DATA Data;
+} RSC_DATA_ENTRY;
/**
Register the callback function for ReportStatusCode() notification.
diff --git a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
index b740db4267..c9c54e8381 100644
--- a/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
@@ -39,6 +39,7 @@
[LibraryClasses]
UefiRuntimeLib
MemoryAllocationLib
+ BaseMemoryLib
UefiBootServicesTableLib
UefiDriverEntryPoint
HobLib
@@ -46,6 +47,7 @@
DebugLib
BaseLib
SynchronizationLib
+ UefiLib
[Guids]
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event