]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystem.c
MdeModulePkg/ResetSystemRuntimeDxe: Add platform filter and handler
[mirror_edk2.git] / MdeModulePkg / Universal / ResetSystemRuntimeDxe / ResetSystem.c
index 75cff3777358e9ead41ce32438ea84e21feb90b9..fed527fac2dbca7f9dfd1e50fbe82b90c504cbcc 100644 (file)
 \r
 #include "ResetSystem.h"\r
 \r
+//\r
+// The current ResetSystem() notification recursion depth\r
+//\r
+UINTN  mResetNotifyDepth = 0;\r
+\r
 /**\r
   Register a notification function to be called when ResetSystem() is called.\r
 \r
@@ -130,6 +135,24 @@ RESET_NOTIFICATION_INSTANCE mResetNotification = {
   INITIALIZE_LIST_HEAD_VARIABLE (mResetNotification.ResetNotifies)\r
 };\r
 \r
+RESET_NOTIFICATION_INSTANCE mPlatformSpecificResetFilter = {\r
+  RESET_NOTIFICATION_INSTANCE_SIGNATURE,\r
+  {\r
+    RegisterResetNotify,\r
+    UnregisterResetNotify\r
+  },\r
+  INITIALIZE_LIST_HEAD_VARIABLE (mPlatformSpecificResetFilter.ResetNotifies)\r
+};\r
+\r
+RESET_NOTIFICATION_INSTANCE mPlatformSpecificResetHandler = {\r
+  RESET_NOTIFICATION_INSTANCE_SIGNATURE,\r
+  {\r
+    RegisterResetNotify,\r
+    UnregisterResetNotify\r
+  },\r
+  INITIALIZE_LIST_HEAD_VARIABLE (mPlatformSpecificResetHandler.ResetNotifies)\r
+};\r
+\r
 /**\r
   The driver's entry point.\r
 \r
@@ -170,6 +193,8 @@ InitializeResetSystem (
                   &Handle,\r
                   &gEfiResetArchProtocolGuid,         NULL,\r
                   &gEfiResetNotificationProtocolGuid, &mResetNotification.ResetNotification,\r
+                  &gEdkiiPlatformSpecificResetFilterProtocolGuid, &mPlatformSpecificResetFilter.ResetNotification,\r
+                  &gEdkiiPlatformSpecificResetHandlerProtocolGuid, &mPlatformSpecificResetHandler.ResetNotification,\r
                   NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
@@ -225,13 +250,44 @@ ResetSystem (
   UINTN               CapsuleDataPtr;\r
   LIST_ENTRY          *Link;\r
   RESET_NOTIFY_ENTRY  *Entry;\r
-  \r
+\r
+  //\r
+  // Above the maximum recursion depth, so do the smallest amount of\r
+  // work to perform a cold reset.\r
+  //\r
+  if (mResetNotifyDepth >= MAX_RESET_NOTIFY_DEPTH) {\r
+    ResetCold ();\r
+    ASSERT (FALSE);\r
+    return;\r
+  }\r
+\r
   //\r
-  // Indicate reset system runtime service is called.\r
+  // Only do REPORT_STATUS_CODE() on first call to ResetSystem()\r
   //\r
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_RESET_SYSTEM));\r
+  if (mResetNotifyDepth == 0) {\r
+    //\r
+    // Indicate reset system runtime service is called.\r
+    //\r
+    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_RESET_SYSTEM));\r
+  }\r
 \r
-  if (!EfiAtRuntime ()) {\r
+  mResetNotifyDepth++;\r
+  if (!EfiAtRuntime () && mResetNotifyDepth < MAX_RESET_NOTIFY_DEPTH) {\r
+    //\r
+    // Call reset notification functions registered through the\r
+    // EDKII_PLATFORM_SPECIFIC_RESET_FILTER_PROTOCOL.\r
+    //\r
+    for ( Link = GetFirstNode (&mPlatformSpecificResetFilter.ResetNotifies)\r
+        ; !IsNull (&mPlatformSpecificResetFilter.ResetNotifies, Link)\r
+        ; Link = GetNextNode (&mPlatformSpecificResetFilter.ResetNotifies, Link)\r
+        ) {\r
+      Entry = RESET_NOTIFY_ENTRY_FROM_LINK (Link);\r
+      Entry->ResetNotify (ResetType, ResetStatus, DataSize, ResetData);\r
+    }\r
+    //\r
+    // Call reset notification functions registered through the\r
+    // EFI_RESET_NOTIFICATION_PROTOCOL.\r
+    //\r
     for ( Link = GetFirstNode (&mResetNotification.ResetNotifies)\r
         ; !IsNull (&mResetNotification.ResetNotifies, Link)\r
         ; Link = GetNextNode (&mResetNotification.ResetNotifies, Link)\r
@@ -239,6 +295,17 @@ ResetSystem (
       Entry = RESET_NOTIFY_ENTRY_FROM_LINK (Link);\r
       Entry->ResetNotify (ResetType, ResetStatus, DataSize, ResetData);\r
     }\r
+    //\r
+    // call reset notification functions registered through the \r
+    // EDKII_PLATFORM_SPECIFIC_RESET_HANDLER_PROTOCOL.\r
+    //\r
+    for ( Link = GetFirstNode (&mPlatformSpecificResetHandler.ResetNotifies)\r
+        ; !IsNull (&mPlatformSpecificResetHandler.ResetNotifies, Link)\r
+        ; Link = GetNextNode (&mPlatformSpecificResetHandler.ResetNotifies, Link)\r
+        ) {\r
+      Entry = RESET_NOTIFY_ENTRY_FROM_LINK (Link);\r
+      Entry->ResetNotify (ResetType, ResetStatus, DataSize, ResetData);\r
+    }\r
   }\r
 \r
   switch (ResetType) {\r