]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c
MdePkg: Fix typos in comments
[mirror_edk2.git] / MdePkg / Library / SmmPeriodicSmiLib / SmmPeriodicSmiLib.c
index a941d75e5f1e6bb095a15d4624fb37b00d8d1dab..2016af60d87b729c755f0da52ca2bbf8290f03ba 100644 (file)
 #include <Library/SmmPeriodicSmiLib.h>\r
 \r
 ///\r
-/// Define the number of periodic SMI handler entries that should be allocated in \r
-/// the constructor for gPeriodicSmiLibraryHandlers and also use this value as the \r
-/// number of entries to add to gPeriodicSmiLibraryHandlers when gPeriodicSmiLibraryHandlers\r
-/// is full.\r
+/// Define the number of periodic SMI handler entries that should be allocated to the list\r
+/// of free periodic SMI handlers when the list of free periodic SMI handlers is empty.\r
 ///\r
 #define PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE  0x08\r
 \r
@@ -48,6 +46,10 @@ typedef struct {
   ///\r
   UINT32                                   Signature;\r
   ///\r
+  /// The link entry to be inserted to the list of periodic SMI handlers.\r
+  ///\r
+  LIST_ENTRY                               Link;\r
+  ///\r
   /// The dispatch function to called to invoke an enabled periodic SMI handler.\r
   ///\r
   PERIODIC_SMI_LIBRARY_HANDLER             DispatchFunction;\r
@@ -155,6 +157,19 @@ typedef struct {
     PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE                    \\r
     )\r
 \r
+/**\r
+ Macro that returns a pointer to a PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT \r
+ structure based on a pointer to a Link field.\r
+\r
+**/\r
+#define PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK(a)             \\r
+  CR (                                                                \\r
+    a,                                                                \\r
+    PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT,                             \\r
+    Link,                                                             \\r
+    PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE                    \\r
+    )\r
+\r
 ///\r
 /// Pointer to the SMM Periodic Timer Disatch Protocol that was located in the constuctor.\r
 ///\r
@@ -170,21 +185,22 @@ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL  *gSmmPeriodicTimerDispatch2
 UINT64                                     *gSmiTickPeriodTable                  = NULL;\r
 \r
 ///\r
-/// The number entries in gPeriodicSmiLibraryHandlers\r
+/// Linked list of free periodic SMI handlers that this library can use.\r
 ///\r
-UINTN                                      gNumberOfPeriodicSmiLibraryHandlers   = 0;\r
+LIST_ENTRY                                 gFreePeriodicSmiLibraryHandlers       =\r
+                                           INITIALIZE_LIST_HEAD_VARIABLE (gFreePeriodicSmiLibraryHandlers);\r
 \r
 ///\r
-/// Table of periodic SMI handlers that this library is currently managing.  This\r
-/// table is allocated using AllocatePool()\r
+/// Linked list of periodic SMI handlers that this library is currently managing.\r
 ///\r
-PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT       *gPeriodicSmiLibraryHandlers          = NULL;\r
+LIST_ENTRY                                 gPeriodicSmiLibraryHandlers           =\r
+                                           INITIALIZE_LIST_HEAD_VARIABLE (gPeriodicSmiLibraryHandlers);\r
 \r
 ///\r
-/// The index of gPeriodicSmiLibraryHandlers that is currently being executed.  \r
-/// Is set to -1 if no periodic SMI handler is currently being executed.\r
+/// Pointer to the periodic SMI handler that is currently being executed.\r
+/// Is set to NULL if no periodic SMI handler is currently being executed.\r
 ///\r
-INTN                                       gActivePeriodicSmiLibraryHandlerIndex = -1;\r
+PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT       *gActivePeriodicSmiLibraryHandler     = NULL;\r
 \r
 /**\r
   Internal worker function that returns a pointer to the \r
@@ -202,18 +218,7 @@ GetActivePeriodicSmiLibraryHandler (
   VOID\r
   )\r
 {\r
-  if (gActivePeriodicSmiLibraryHandlerIndex < 0) {\r
-    //\r
-    // Return NULL if index is negative, which means that there is no active \r
-    // periodic SMI handler.\r
-    //\r
-    return NULL;\r
-  }\r
-  \r
-  //\r
-  // Return a pointer to the active periodic SMI handler context\r
-  //\r
-  return &gPeriodicSmiLibraryHandlers[gActivePeriodicSmiLibraryHandlerIndex];\r
+  return gActivePeriodicSmiLibraryHandler;\r
 }\r
 \r
 /**\r
@@ -240,24 +245,30 @@ GetActivePeriodicSmiLibraryHandler (
 **/\r
 PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT *\r
 LookupPeriodicSmiLibraryHandler (\r
-  IN EFI_HANDLE  DispatchHandle    OPTIONAL\r
+  IN EFI_HANDLE                         DispatchHandle    OPTIONAL\r
   )\r
 {\r
-  UINTN  Index;\r
+  LIST_ENTRY                            *Link;\r
+  PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT  *PeriodicSmiLibraryHandler;\r
 \r
   //\r
   // If DispatchHandle is NULL, then return the active periodic SMI handler\r
-  //  \r
+  //\r
   if (DispatchHandle == NULL) {\r
     return GetActivePeriodicSmiLibraryHandler ();\r
   }\r
 \r
   //\r
   // Search the periodic SMI handler entries for a a matching DispatchHandle\r
-  //  \r
-  for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {\r
-    if (gPeriodicSmiLibraryHandlers[Index].DispatchHandle == DispatchHandle) {\r
-      return &gPeriodicSmiLibraryHandlers[Index];\r
+  //\r
+  for ( Link = GetFirstNode (&gPeriodicSmiLibraryHandlers)\r
+      ; !IsNull (&gPeriodicSmiLibraryHandlers, Link)\r
+      ; Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link)\r
+      ) {\r
+    PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);\r
+\r
+    if (PeriodicSmiLibraryHandler->DispatchHandle == DispatchHandle) {\r
+      return PeriodicSmiLibraryHandler;\r
     }\r
   }\r
   \r
@@ -285,15 +296,66 @@ SetActivePeriodicSmiLibraryHandler (
   IN CONST VOID  *Context  OPTIONAL\r
   )\r
 {\r
+  if (Context == NULL) {\r
+    gActivePeriodicSmiLibraryHandler = NULL;\r
+  } else {\r
+    gActivePeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_REGISTER_CONTEXT (Context);\r
+  }\r
+  return gActivePeriodicSmiLibraryHandler;\r
+}\r
+\r
+/**\r
+  Internal worker function that moves the specified periodic SMI handler from the\r
+  list of managed periodic SMI handlers to the list of free periodic SMI handlers.\r
+\r
+  @param[in] PeriodicSmiLibraryHandler  Pointer to the periodic SMI handler to be reclaimed.\r
+**/\r
+VOID\r
+ReclaimPeriodicSmiLibraryHandler (\r
+  PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT     *PeriodicSmiLibraryHandler\r
+  )\r
+{\r
+  ASSERT (PeriodicSmiLibraryHandler->DispatchHandle == NULL);\r
+  if (PeriodicSmiLibraryHandler->Stack != NULL) {\r
+    FreePages (\r
+      PeriodicSmiLibraryHandler->Stack,\r
+      EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)\r
+      );\r
+    PeriodicSmiLibraryHandler->Stack = NULL;\r
+  }\r
+  RemoveEntryList (&PeriodicSmiLibraryHandler->Link);\r
+  InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);\r
+}\r
+\r
+/**\r
+  Add the additional entries to the list of free periodic SMI handlers.\r
+  The function is assumed to be called only when the list of free periodic SMI\r
+  handlers is empty.\r
+\r
+  @retval TRUE  The additional entries were added.\r
+  @retval FALSE There was no available resource for the additional entries.\r
+**/\r
+BOOLEAN\r
+EnlargeFreePeriodicSmiLibraryHandlerList (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                                 Index;\r
   PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT  *PeriodicSmiLibraryHandler;\r
 \r
-  if (Context == NULL) {\r
-    gActivePeriodicSmiLibraryHandlerIndex = -1;\r
-    return NULL;\r
+  //\r
+  // Add the entries to the list\r
+  //\r
+  for (Index = 0; Index < PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE; Index++) {\r
+    PeriodicSmiLibraryHandler = AllocatePool (sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT));\r
+    if (PeriodicSmiLibraryHandler == NULL) {\r
+      break;\r
+    }\r
+    PeriodicSmiLibraryHandler->Signature = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE;\r
+    InsertHeadList (&gFreePeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);\r
   }\r
-  PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_REGISTER_CONTEXT (Context);\r
-  gActivePeriodicSmiLibraryHandlerIndex = PeriodicSmiLibraryHandler - gPeriodicSmiLibraryHandlers;\r
-  return PeriodicSmiLibraryHandler;\r
+\r
+  return (BOOLEAN) (Index > 0);\r
 }\r
 \r
 /**\r
@@ -310,40 +372,24 @@ FindFreePeriodicSmiLibraryHandler (
   VOID\r
   )\r
 {\r
-  UINTN                                 Index;\r
   PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT  *PeriodicSmiLibraryHandler;\r
   \r
-  //\r
-  // Search for a free entry in gPeriodicSmiLibraryHandlers\r
-  // A free entry must have a NULL DispatchHandle and a NULL Stack.\r
-  //  \r
-  for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {\r
-    if (gPeriodicSmiLibraryHandlers[Index].DispatchHandle != NULL) {\r
-      continue;\r
-    }\r
-    if (gPeriodicSmiLibraryHandlers[Index].Stack != NULL) {\r
-      continue;\r
+  if (IsListEmpty (&gFreePeriodicSmiLibraryHandlers)) {\r
+    if (!EnlargeFreePeriodicSmiLibraryHandlerList ()) {\r
+      return NULL;\r
     }\r
-    return &gPeriodicSmiLibraryHandlers[Index];\r
   }\r
 \r
   //\r
-  // If no free entries were found, then grow the table of periodic SMI handler entries\r
+  // Get one from the list of free periodic SMI handlers.\r
   //\r
-  if (Index == gNumberOfPeriodicSmiLibraryHandlers) {\r
-    PeriodicSmiLibraryHandler = ReallocatePool (\r
-                                  gNumberOfPeriodicSmiLibraryHandlers * sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT),\r
-                                  (gNumberOfPeriodicSmiLibraryHandlers + PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE) * sizeof (PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT),\r
-                                  gPeriodicSmiLibraryHandlers\r
-                                  );\r
-    if (PeriodicSmiLibraryHandler == NULL) {\r
-      return NULL;\r
-    }\r
-    gPeriodicSmiLibraryHandlers = PeriodicSmiLibraryHandler;\r
-    gNumberOfPeriodicSmiLibraryHandlers += PERIODIC_SMI_LIBRARY_ALLOCATE_SIZE;\r
-  }\r
+  PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (\r
+                                GetFirstNode (&gFreePeriodicSmiLibraryHandlers)\r
+                                );\r
+  RemoveEntryList (&PeriodicSmiLibraryHandler->Link);\r
+  InsertTailList (&gPeriodicSmiLibraryHandlers, &PeriodicSmiLibraryHandler->Link);\r
 \r
-  return &gPeriodicSmiLibraryHandlers[Index];\r
+  return PeriodicSmiLibraryHandler;\r
 }\r
 \r
 /**\r
@@ -499,7 +545,7 @@ PeriodicSmiExit (
   If this function is not called from within an enabled periodic SMI handler, \r
   then 0 is returned.\r
 \r
-  @return  The actual time in 100ns units elasped since this function was\r
+  @return  The actual time in 100ns units elapsed since this function was\r
            called.  A value of 0 indicates an unknown amount of time.\r
 \r
 **/\r
@@ -687,7 +733,7 @@ PeriodicSmiDispatchFunctionOnCpu (
   released to notify the CPU that is running the SMM Foundation that the periodic\r
   SMI handler execution has finished its execution.\r
 \r
-  @param[in] Buffer  A pointer to the context for the periodic SMI handler.\r
+  @param[in, out] Buffer  A pointer to the context for the periodic SMI handler.\r
 \r
 **/\r
 VOID\r
@@ -722,10 +768,10 @@ PeriodicSmiDispatchFunctionWithLock (
                                  SmiHandlerRegister().\r
   @param[in]     Context         Points to an optional handler context which was \r
                                  specified when the handler was registered.\r
-  @param[in,out] CommBuffer      A pointer to a collection of data in memory that\r
+  @param[in, out] CommBuffer     A pointer to a collection of data in memory that\r
                                  will be conveyed from a non-SMM environment into \r
                                  an SMM environment.\r
-  @param[in,out] CommBufferSize  The size of the CommBuffer.\r
+  @param[in, out] CommBufferSize The size of the CommBuffer.\r
 \r
   @retval EFI_SUCCESS                         The interrupt was handled and quiesced.\r
                                               No other handlers should still be called.\r
@@ -807,27 +853,12 @@ PeriodicSmiDispatchFunction (
     //\r
     ReleaseSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);\r
   }\r
-  \r
+\r
   //\r
-  // Retrieve the active periodic SMI handler in case the entries were reallocated\r
-  // when the active periodic SMI handler was dispatched.\r
+  // Reclaim the active periodic SMI handler if it was disabled during the current dispatch.\r
   //\r
-  PeriodicSmiLibraryHandler = GetActivePeriodicSmiLibraryHandler ();\r
-  if (PeriodicSmiLibraryHandler != NULL) {\r
-    //\r
-    // If the active periodic SMI handler was disabled during the current dispatch \r
-    // and the periodic SMI handler was allocated a stack when it was enabled, then \r
-    // free that stack here.\r
-    //\r
-    if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) {\r
-      if (PeriodicSmiLibraryHandler->Stack != NULL) {\r
-        FreePages (\r
-          PeriodicSmiLibraryHandler->Stack, \r
-          EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)\r
-          );\r
-        PeriodicSmiLibraryHandler->Stack = NULL;  \r
-      }\r
-    }\r
+  if (PeriodicSmiLibraryHandler->DispatchHandle == NULL) {\r
+    ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);\r
   }\r
   \r
   //\r
@@ -841,7 +872,7 @@ PeriodicSmiDispatchFunction (
 /**\r
   This function enables a periodic SMI handler.\r
   \r
-  @param[in,out] DispatchHandle    A pointer to the handle associated with the \r
+  @param[in, out] DispatchHandle   A pointer to the handle associated with the \r
                                    enabled periodic SMI handler.  This is an \r
                                    optional parameter that may be NULL.  If it is \r
                                    NULL, then the handle will not be returned, \r
@@ -923,8 +954,7 @@ PeriodicSmiEnable (
 \r
   //\r
   // Initialize a new periodic SMI handler entry\r
-  //  \r
-  PeriodicSmiLibraryHandler->Signature        = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_SIGNATURE;\r
+  //\r
   PeriodicSmiLibraryHandler->YieldFlag        = FALSE;\r
   PeriodicSmiLibraryHandler->DispatchHandle   = NULL;\r
   PeriodicSmiLibraryHandler->DispatchFunction = DispatchFunction;\r
@@ -937,6 +967,8 @@ PeriodicSmiEnable (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     ZeroMem (PeriodicSmiLibraryHandler->Stack, PeriodicSmiLibraryHandler->StackSize);\r
+  } else {\r
+    PeriodicSmiLibraryHandler->Stack = NULL;\r
   }\r
   InitializeSpinLock (&PeriodicSmiLibraryHandler->DispatchLock);\r
   PeriodicSmiLibraryHandler->PerfomanceCounterRate = GetPerformanceCounterProperties (\r
@@ -951,18 +983,9 @@ PeriodicSmiEnable (
                                          &PeriodicSmiLibraryHandler->RegisterContext,\r
                                          &PeriodicSmiLibraryHandler->DispatchHandle\r
                                          );\r
-  if (EFI_ERROR (Status) || PeriodicSmiLibraryHandler->DispatchHandle == NULL) {\r
-    //\r
-    // If the registration failed or the handle is invalid, free the stack if one was allocated\r
-    //\r
-    if (PeriodicSmiLibraryHandler->Stack != NULL) {\r
-      FreePages (\r
-        PeriodicSmiLibraryHandler->Stack, \r
-        EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)\r
-        );\r
-      PeriodicSmiLibraryHandler->Stack = NULL;  \r
-    }\r
+  if (EFI_ERROR (Status)) {\r
     PeriodicSmiLibraryHandler->DispatchHandle = NULL;\r
+    ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   \r
@@ -1021,25 +1044,15 @@ PeriodicSmiDisable (
   }\r
 \r
   //\r
-  // If active periodic SMI handler is not the periodic SMI handler being \r
-  // disabled, and the periodic SMI handler being disabled was allocated a \r
-  // stack when it was enabled, then free the stack.\r
+  // Mark the entry for the disabled periodic SMI handler as free, and\r
+  // call ReclaimPeriodicSmiLibraryHandler to move it to the list of free\r
+  // periodic SMI handlers.\r
   //\r
+  PeriodicSmiLibraryHandler->DispatchHandle = NULL;\r
   if (PeriodicSmiLibraryHandler != GetActivePeriodicSmiLibraryHandler ()) {\r
-    if (PeriodicSmiLibraryHandler->Stack != NULL) {\r
-      FreePages (\r
-        PeriodicSmiLibraryHandler->Stack, \r
-        EFI_SIZE_TO_PAGES (PeriodicSmiLibraryHandler->StackSize)\r
-        );\r
-      PeriodicSmiLibraryHandler->Stack = NULL;  \r
-    }\r
+    ReclaimPeriodicSmiLibraryHandler (PeriodicSmiLibraryHandler);\r
   }\r
-  \r
-  //\r
-  // Mark the entry for the disabled periodic SMI handler as free\r
-  //\r
-  PeriodicSmiLibraryHandler->DispatchHandle = NULL;\r
-  \r
+\r
   return TRUE;\r
 }\r
 \r
@@ -1111,12 +1124,12 @@ SmmPeriodicSmiLibConstructor (
       gSmiTickPeriodTable[Count] = *SmiTickInterval;\r
     }\r
     Count++;\r
-  } while (SmiTickInterval != NULL);                                           \r
+  } while (SmiTickInterval != NULL);\r
 \r
   //\r
   // Allocate buffer for initial set of periodic SMI handlers\r
   //\r
-  FindFreePeriodicSmiLibraryHandler ();\r
+  EnlargeFreePeriodicSmiLibraryHandlerList ();\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1138,28 +1151,33 @@ SmmPeriodicSmiLibDestructor (
   IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  UINTN  Index;\r
+  LIST_ENTRY                            *Link;\r
+  PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT  *PeriodicSmiLibraryHandler;\r
 \r
   //\r
   // Free the table of supported periodic SMI tick rates\r
-  //  \r
+  //\r
   if (gSmiTickPeriodTable != NULL) {\r
     FreePool (gSmiTickPeriodTable);\r
   }\r
 \r
   //\r
   // Disable all periodic SMI handlers\r
-  //  \r
-  for (Index = 0; Index < gNumberOfPeriodicSmiLibraryHandlers; Index++) {\r
-    PeriodicSmiDisable (gPeriodicSmiLibraryHandlers[Index].DispatchHandle);\r
+  //\r
+  for (Link = GetFirstNode (&gPeriodicSmiLibraryHandlers); !IsNull (&gPeriodicSmiLibraryHandlers, Link);) {\r
+    PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);\r
+    Link = GetNextNode (&gPeriodicSmiLibraryHandlers, Link);\r
+    PeriodicSmiDisable (PeriodicSmiLibraryHandler->DispatchHandle);\r
   }\r
-  \r
+\r
   //\r
   // Free all the periodic SMI handler entries\r
   //\r
-  if (gPeriodicSmiLibraryHandlers != NULL) {\r
-    FreePool (gPeriodicSmiLibraryHandlers);\r
+  for (Link = GetFirstNode (&gFreePeriodicSmiLibraryHandlers); !IsNull (&gFreePeriodicSmiLibraryHandlers, Link);) {    \r
+    PeriodicSmiLibraryHandler = PERIODIC_SMI_LIBRARY_HANDLER_CONTEXT_FROM_LINK (Link);\r
+    Link = RemoveEntryList (Link);\r
+    FreePool (PeriodicSmiLibraryHandler);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r