/** @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
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
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
// 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