]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.c
ArmPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ArmPkg / Library / ArmSmcPsciResetSystemLib / ArmSmcPsciResetSystemLib.c
index 10ceafd14d5de0de5465817615f7650a81ae7073..87c1ea0ed032f507fac6ece90013a059b3018952 100644 (file)
@@ -1,15 +1,9 @@
 /** @file\r
   ResetSystemLib implementation using PSCI calls\r
 \r
-  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2017 - 2018, Linaro Ltd. All rights reserved.<BR>\r
 \r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution. The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -81,6 +75,8 @@ ResetShutdown (
   ArmCallSmc (&ArmSmcArgs);\r
 }\r
 \r
+VOID DisableMmuAndReenterPei (VOID);\r
+\r
 /**\r
   This function causes the system to enter S3 and then wake up immediately.\r
 \r
@@ -92,7 +88,12 @@ EnterS3WithImmediateWake (
   VOID\r
   )\r
 {\r
-  VOID (*Reset)(VOID);\r
+  EFI_PHYSICAL_ADDRESS        Alloc;\r
+  EFI_MEMORY_DESCRIPTOR       *MemMap;\r
+  UINTN                       MemMapSize;\r
+  UINTN                       MapKey, DescriptorSize;\r
+  UINT32                      DescriptorVersion;\r
+  EFI_STATUS                  Status;\r
 \r
   if (FeaturePcdGet (PcdArmReenterPeiForCapsuleWarmReboot) &&\r
       !EfiAtRuntime ()) {\r
@@ -101,11 +102,49 @@ EnterS3WithImmediateWake (
     // immediate wake (which is used by capsule update) by disabling the MMU\r
     // and interrupts, and jumping to the PEI entry point.\r
     //\r
-    Reset = (VOID (*)(VOID))(UINTN)FixedPcdGet64 (PcdFvBaseAddress);\r
 \r
-    gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
-    ArmDisableMmu ();\r
-    Reset ();\r
+    //\r
+    // Obtain the size of the memory map\r
+    //\r
+    MemMapSize = 0;\r
+    MemMap = NULL;\r
+    Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,\r
+                    &DescriptorVersion);\r
+    ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+    //\r
+    // Add some slack to the allocation to cater for changes in the memory\r
+    // map if ExitBootServices () fails the first time around.\r
+    //\r
+    MemMapSize += SIZE_4KB;\r
+    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,\r
+                    EFI_SIZE_TO_PAGES (MemMapSize), &Alloc);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    MemMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN)Alloc;\r
+\r
+    Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,\r
+                    &DescriptorVersion);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // ExitBootServices () may fail the first time around if an event fired\r
+      // right after the call to GetMemoryMap() which allocated or freed memory.\r
+      // Since that first call to ExitBootServices () will disarm the timer,\r
+      // this is guaranteed not to happen again, so one additional attempt\r
+      // should suffice.\r
+      //\r
+      Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,\r
+                      &DescriptorVersion);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+\r
+    DisableMmuAndReenterPei ();\r
   }\r
 }\r
 \r