+/** @file\r
+* High memory node enumeration DXE driver for ARM Virtual Machines\r
+*\r
+* Copyright (c) 2015, Linaro Ltd. All rights reserved.\r
+*\r
+* This program and the accompanying materials are licensed and made available\r
+* under the terms and conditions of the BSD License which accompanies this\r
+* 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\r
+* IMPLIED.\r
+*\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/HobLib.h>\r
+#include <libfdt.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeHighMemDxe (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ VOID *Hob;\r
+ VOID *DeviceTreeBase;\r
+ INT32 Node, Prev;\r
+ EFI_STATUS Status;\r
+ CONST CHAR8 *Type;\r
+ INT32 Len;\r
+ CONST VOID *RegProp;\r
+ UINT64 CurBase;\r
+ UINT64 CurSize;\r
+\r
+ Hob = GetFirstGuidHob(&gFdtHobGuid);\r
+ if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);\r
+\r
+ if (fdt_check_header (DeviceTreeBase) != 0) {\r
+ DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__,\r
+ DeviceTreeBase));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
+\r
+ //\r
+ // Check for memory node and add the memory spaces expect the lowest one\r
+ //\r
+ for (Prev = 0;; Prev = Node) {\r
+ Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
+ if (Node < 0) {\r
+ break;\r
+ }\r
+\r
+ Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);\r
+ if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {\r
+ //\r
+ // Get the 'reg' property of this node. For now, we will assume\r
+ // two 8 byte quantities for base and size, respectively.\r
+ //\r
+ RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
+ if (RegProp != NULL && Len == (2 * sizeof (UINT64))) {\r
+\r
+ CurBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
+ CurSize = fdt64_to_cpu (((UINT64 *)RegProp)[1]);\r
+\r
+ if (FixedPcdGet64 (PcdSystemMemoryBase) != CurBase) {\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeSystemMemory,\r
+ CurBase, CurSize,\r
+ EFI_MEMORY_WB | EFI_MEMORY_WC |\r
+ EFI_MEMORY_WT | EFI_MEMORY_UC);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR,\r
+ "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",\r
+ __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r
+ continue;\r
+ }\r
+\r
+ Status = gDS->SetMemorySpaceAttributes (\r
+ CurBase, CurSize,\r
+ EFI_MEMORY_WB);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR,\r
+ "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",\r
+ __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",\r
+ __FUNCTION__, CurBase, CurBase + CurSize - 1));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r