]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Fix the issue that callback function with TPL lower than TPL_HIGH_LEVEL cannot handle...
authorxli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 16 Dec 2009 04:50:57 +0000 (04:50 +0000)
committerxli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 16 Dec 2009 04:50:57 +0000 (04:50 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9568 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.c
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.h
MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf

index aa2fa100f05da0a33b63d3026c96825c3dd39e7c..a8c43a0d62a3acc43c0fac16ff4e5ce6df02ec3a 100644 (file)
@@ -34,6 +34,49 @@ EFI_RSC_HANDLER_PROTOCOL  mRscHandlerProtocol = {
   Unregister\r
   };\r
 \r
+/**\r
+  Event callback function to invoke status code handler in list.\r
+\r
+  @param  Event         Event whose notification function is being invoked.\r
+  @param  Context       Pointer to the notification function's context, which is\r
+                        always zero in current implementation.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RscHandlerNotification (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  RSC_HANDLER_CALLBACK_ENTRY  *CallbackEntry;\r
+  EFI_PHYSICAL_ADDRESS        Address;\r
+  RSC_DATA_ENTRY              *RscData;\r
+\r
+  CallbackEntry = (RSC_HANDLER_CALLBACK_ENTRY *) Context;\r
+\r
+  //\r
+  // Traverse the status code data buffer to parse all\r
+  // data to report.\r
+  //\r
+  Address = CallbackEntry->StatusCodeDataBuffer;\r
+  while (Address < CallbackEntry->EndPointer) {\r
+    RscData = (RSC_DATA_ENTRY *) (UINTN) Address;\r
+    CallbackEntry->RscHandlerCallback (\r
+                     RscData->Type,\r
+                     RscData->Value,\r
+                     RscData->Instance,\r
+                     &RscData->CallerId,\r
+                     &RscData->Data\r
+                     );\r
+\r
+    Address += (sizeof (RSC_DATA_ENTRY) + RscData->Data.Size);\r
+    Address  = ALIGN_VARIABLE (Address);\r
+  }\r
+\r
+  CallbackEntry->EndPointer = CallbackEntry->StatusCodeDataBuffer;\r
+}\r
+\r
 /**\r
   Register the callback function for ReportStatusCode() notification.\r
   \r
@@ -69,6 +112,7 @@ Register (
   IN EFI_TPL                    Tpl\r
   )\r
 {\r
+  EFI_STATUS                    Status;\r
   LIST_ENTRY                    *Link;\r
   RSC_HANDLER_CALLBACK_ENTRY    *CallbackEntry;\r
 \r
@@ -86,13 +130,35 @@ Register (
     }\r
   }\r
 \r
-  CallbackEntry = AllocatePool (sizeof (RSC_HANDLER_CALLBACK_ENTRY));\r
+  CallbackEntry = AllocateZeroPool (sizeof (RSC_HANDLER_CALLBACK_ENTRY));\r
   ASSERT (CallbackEntry != NULL);\r
 \r
   CallbackEntry->Signature          = RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE;\r
   CallbackEntry->RscHandlerCallback = Callback;\r
   CallbackEntry->Tpl                = Tpl;\r
 \r
+  //\r
+  // If TPL of registered callback funtion is not TPL_HIGH_LEVEL, then event should be created\r
+  // for it, and related buffer for status code data should be prepared.\r
+  // Here the data buffer must be prepared in advance, because Report Status Code Protocol might\r
+  // be invoked under TPL_HIGH_LEVEL and no memory allocation is allowed then.\r
+  // If TPL is TPL_HIGH_LEVEL, then all status code will be reported immediately, without data\r
+  // buffer and event trigger.\r
+  //\r
+  if (Tpl != TPL_HIGH_LEVEL) {\r
+    CallbackEntry->StatusCodeDataBuffer = (EFI_PHYSICAL_ADDRESS) AllocatePool (EFI_PAGE_SIZE);\r
+    CallbackEntry->BufferSize           = EFI_PAGE_SIZE;\r
+    CallbackEntry->EndPointer           = CallbackEntry->StatusCodeDataBuffer;\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    Tpl,\r
+                    RscHandlerNotification,\r
+                    CallbackEntry,\r
+                    &CallbackEntry->Event\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
   InsertTailList (&mCallbackListHead, &CallbackEntry->Node);\r
 \r
   return EFI_SUCCESS;\r
@@ -131,6 +197,10 @@ Unregister (
       //\r
       // If the function is found in list, delete it and return.\r
       //\r
+      if (CallbackEntry->Tpl != TPL_HIGH_LEVEL) {\r
+        FreePool ((VOID *) (UINTN) CallbackEntry->StatusCodeDataBuffer);\r
+        gBS->CloseEvent (CallbackEntry->Event);\r
+      }\r
       RemoveEntryList (&CallbackEntry->Node);\r
       FreePool (CallbackEntry);\r
       return EFI_SUCCESS;\r
@@ -140,34 +210,6 @@ Unregister (
   return EFI_NOT_FOUND;\r
 }\r
 \r
-/**\r
-  Event callback function to invoke status code handler in list.\r
-\r
-  @param  Event         Event whose notification function is being invoked.\r
-  @param  Context       Pointer to the notification function's context, which is\r
-                        always zero in current implementation.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-RscHandlerNotification (\r
-  IN EFI_EVENT        Event,\r
-  IN VOID             *Context\r
-  )\r
-{\r
-  RSC_EVENT_CONTEXT  *RscContext;\r
-\r
-  RscContext = (RSC_EVENT_CONTEXT *) Context;\r
-\r
-  RscContext->RscHandlerCallback (\r
-                RscContext->Type,\r
-                RscContext->Value,\r
-                RscContext->Instance,\r
-                RscContext->CallerId,\r
-                RscContext->Data\r
-                );\r
-}\r
-\r
 /**\r
   Provides an interface that a software module can call to report a status code.\r
 \r
@@ -198,9 +240,9 @@ ReportDispatcher (
 {\r
   LIST_ENTRY                    *Link;\r
   RSC_HANDLER_CALLBACK_ENTRY    *CallbackEntry;\r
-  RSC_EVENT_CONTEXT             Context;\r
-  EFI_EVENT                     Event;\r
+  RSC_DATA_ENTRY                *RscData;\r
   EFI_STATUS                    Status;\r
+  VOID                          *NewBuffer;\r
 \r
   //\r
   // Use atom operation to avoid the reentant of report.\r
@@ -224,26 +266,53 @@ ReportDispatcher (
       continue;\r
     }\r
 \r
-    Context.RscHandlerCallback = CallbackEntry->RscHandlerCallback;\r
-    Context.Type               = Type;\r
-    Context.Value              = Value;\r
-    Context.Instance           = Instance;\r
-    Context.CallerId           = CallerId;\r
-    Context.Data               = Data;\r
+    //\r
+    // If callback is registered with TPL lower than TPL_HIGH_LEVEL, event must be signaled at boot time to possibly wait for\r
+    // allowed TPL to report status code. Related data should also be stored in data buffer.\r
+    //\r
+    CallbackEntry->EndPointer  = ALIGN_VARIABLE (CallbackEntry->EndPointer);\r
+    RscData = (RSC_DATA_ENTRY *) (UINTN) CallbackEntry->EndPointer;\r
+    CallbackEntry->EndPointer += sizeof (RSC_DATA_ENTRY);\r
+    if (Data != NULL) {\r
+      CallbackEntry->EndPointer += Data->Size;\r
+    }\r
 \r
-    Status = gBS->CreateEvent (\r
-                    EVT_NOTIFY_SIGNAL,\r
-                    CallbackEntry->Tpl,\r
-                    RscHandlerNotification,\r
-                    &Context,\r
-                    &Event\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // 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.\r
+    //\r
+    if (CallbackEntry->EndPointer > (CallbackEntry->StatusCodeDataBuffer + (CallbackEntry->BufferSize / 8) * 7)) {\r
+      if (EfiGetCurrentTpl () < TPL_HIGH_LEVEL) {\r
+        NewBuffer = ReallocatePool (\r
+                      CallbackEntry->BufferSize,\r
+                      CallbackEntry->BufferSize * 2,\r
+                      (VOID *) (UINTN) CallbackEntry->StatusCodeDataBuffer\r
+                      );\r
+        if (NewBuffer != NULL) {\r
+          CallbackEntry->EndPointer = (EFI_PHYSICAL_ADDRESS) NewBuffer + (CallbackEntry->EndPointer - CallbackEntry->StatusCodeDataBuffer);\r
+          CallbackEntry->StatusCodeDataBuffer = (EFI_PHYSICAL_ADDRESS) NewBuffer;\r
+          CallbackEntry->BufferSize *= 2;\r
+        }\r
+      }\r
+    }\r
 \r
-    Status = gBS->SignalEvent (Event);\r
-    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // If data buffer is used up, do not report for this time.\r
+    //\r
+    if (CallbackEntry->EndPointer > (CallbackEntry->StatusCodeDataBuffer + CallbackEntry->BufferSize)) {\r
+      continue;\r
+    }\r
+\r
+    RscData->Type      = Type;\r
+    RscData->Value     = Value;\r
+    RscData->Instance  = Instance;\r
+    if (CallerId != NULL) {\r
+      CopyGuid (&RscData->CallerId, CallerId);\r
+    }\r
+    if (Data != NULL) {\r
+      CopyMem (&RscData->Data, Data, Data->HeaderSize + Data->Size);\r
+    }\r
 \r
-    Status = gBS->CloseEvent (Event);\r
+    Status = gBS->SignalEvent (CallbackEntry->Event);\r
     ASSERT_EFI_ERROR (Status);\r
   }\r
 \r
index a87ad5fdb86ae91705736881ffb540a77eb35827..2b727aba6570b467cb804092da0e1823afca90f1 100644 (file)
@@ -29,7 +29,9 @@
 #include <Library/UefiDriverEntryPoint.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include <Library/UefiRuntimeLib.h>\r
+#include "Library/UefiLib.h"\r
 \r
 #define RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE  SIGNATURE_32 ('r', 'h', 'c', 'e')\r
 \r
@@ -37,17 +39,21 @@ typedef struct {
   UINTN                     Signature;\r
   EFI_RSC_HANDLER_CALLBACK  RscHandlerCallback;\r
   EFI_TPL                   Tpl;\r
+  EFI_EVENT                 Event;\r
+  EFI_PHYSICAL_ADDRESS      StatusCodeDataBuffer;\r
+  UINTN                     BufferSize;\r
+  EFI_PHYSICAL_ADDRESS      EndPointer;\r
   LIST_ENTRY                Node;\r
 } RSC_HANDLER_CALLBACK_ENTRY;\r
 \r
 typedef struct {\r
-  EFI_RSC_HANDLER_CALLBACK RscHandlerCallback;\r
-  EFI_STATUS_CODE_TYPE     Type;\r
-  EFI_STATUS_CODE_VALUE    Value;\r
-  UINT32                   Instance;\r
-  EFI_GUID                 *CallerId;\r
-  EFI_STATUS_CODE_DATA     *Data;\r
-} RSC_EVENT_CONTEXT;\r
+  EFI_STATUS_CODE_TYPE      Type;\r
+  EFI_STATUS_CODE_VALUE     Value;\r
+  UINT32                    Instance;\r
+  UINT32                    Reserved;\r
+  EFI_GUID                  CallerId;\r
+  EFI_STATUS_CODE_DATA      Data;\r
+} RSC_DATA_ENTRY;\r
 \r
 /**\r
   Register the callback function for ReportStatusCode() notification.\r
index b740db426752f3e144a7d247e3fac2166c0db8e8..c9c54e8381facfaaf1df08015ff3d289cdab790f 100644 (file)
@@ -39,6 +39,7 @@
 [LibraryClasses]\r
   UefiRuntimeLib\r
   MemoryAllocationLib\r
+  BaseMemoryLib\r
   UefiBootServicesTableLib\r
   UefiDriverEntryPoint\r
   HobLib\r
@@ -46,6 +47,7 @@
   DebugLib\r
   BaseLib\r
   SynchronizationLib\r
+  UefiLib\r
 \r
 [Guids]\r
   gEfiEventVirtualAddressChangeGuid               ## CONSUMES ## Event\r