--- /dev/null
+#/* @file\r
+#\r
+# Copyright (c) 2016, Linaro Limited. All rights reserved.\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
+#\r
+#*/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/ArmLib.h>\r
+#include <Library/ArmMmuLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArmMmuPeiLibConstructor (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ )\r
+{\r
+ extern UINT32 ArmReplaceLiveTranslationEntrySize;\r
+\r
+ EFI_FV_FILE_INFO FileInfo;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (FileHandle != NULL);\r
+\r
+ Status = (*PeiServices)->FfsGetFileInfo (FileHandle, &FileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Some platforms do not cope very well with cache maintenance being\r
+ // performed on regions backed by NOR flash. Since the firmware image\r
+ // can be assumed to be clean to the PoC when running XIP, even when PEI\r
+ // is executing from DRAM, we only need to perform the cache maintenance\r
+ // when not executing in place.\r
+ //\r
+ if ((UINTN)FileInfo.Buffer <= (UINTN)ArmReplaceLiveTranslationEntry &&\r
+ ((UINTN)FileInfo.Buffer + FileInfo.BufferSize >=\r
+ (UINTN)ArmReplaceLiveTranslationEntry + ArmReplaceLiveTranslationEntrySize)) {\r
+ DEBUG ((EFI_D_INFO, "ArmMmuLib: skipping cache maintenance on XIP PEIM\n"));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "ArmMmuLib: performing cache maintenance on shadowed PEIM\n"));\r
+ //\r
+ // The ArmReplaceLiveTranslationEntry () helper function may be invoked\r
+ // with the MMU off so we have to ensure that it gets cleaned to the PoC\r
+ //\r
+ WriteBackDataCacheRange (ArmReplaceLiveTranslationEntry,\r
+ ArmReplaceLiveTranslationEntrySize);\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r