1 /** @file
2 *  High memory node enumeration DXE driver for ARM Virtual Machines
3 *
4 *  Copyright (c) 2015, Linaro Ltd. All rights reserved.
5 *
6 *  This program and the accompanying materials are licensed and made available
7 *  under the terms and conditions of the BSD License which accompanies this
8 *  distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
13 *  IMPLIED.
14 *
15 **/
16 
17 #include <Library/BaseLib.h>
18 #include <Library/UefiDriverEntryPoint.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/HobLib.h>
22 #include <libfdt.h>
23 #include <Library/DxeServicesTableLib.h>
24 
25 EFI_STATUS
26 EFIAPI
InitializeHighMemDxe(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)27 InitializeHighMemDxe (
28   IN EFI_HANDLE           ImageHandle,
29   IN EFI_SYSTEM_TABLE     *SystemTable
30   )
31 {
32   VOID             *Hob;
33   VOID             *DeviceTreeBase;
34   INT32            Node, Prev;
35   EFI_STATUS       Status;
36   CONST CHAR8      *Type;
37   INT32            Len;
38   CONST VOID       *RegProp;
39   UINT64           CurBase;
40   UINT64           CurSize;
41 
42   Hob = GetFirstGuidHob(&gFdtHobGuid);
43   if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {
44     return EFI_NOT_FOUND;
45   }
46   DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);
47 
48   if (fdt_check_header (DeviceTreeBase) != 0) {
49     DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__,
50       DeviceTreeBase));
51     return EFI_NOT_FOUND;
52   }
53 
54   DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));
55 
56   //
57   // Check for memory node and add the memory spaces expect the lowest one
58   //
59   for (Prev = 0;; Prev = Node) {
60     Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
61     if (Node < 0) {
62       break;
63     }
64 
65     Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
66     if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
67       //
68       // Get the 'reg' property of this node. For now, we will assume
69       // two 8 byte quantities for base and size, respectively.
70       //
71       RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
72       if (RegProp != NULL && Len == (2 * sizeof (UINT64))) {
73 
74         CurBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);
75         CurSize = fdt64_to_cpu (((UINT64 *)RegProp)[1]);
76 
77         if (FixedPcdGet64 (PcdSystemMemoryBase) != CurBase) {
78           Status = gDS->AddMemorySpace (
79                           EfiGcdMemoryTypeSystemMemory,
80                           CurBase, CurSize,
81                           EFI_MEMORY_WB | EFI_MEMORY_WC |
82                           EFI_MEMORY_WT | EFI_MEMORY_UC);
83 
84           if (EFI_ERROR (Status)) {
85             DEBUG ((EFI_D_ERROR,
86               "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
87               __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
88             continue;
89           }
90 
91           Status = gDS->SetMemorySpaceAttributes (
92                           CurBase, CurSize,
93                           EFI_MEMORY_WB);
94 
95           if (EFI_ERROR (Status)) {
96             DEBUG ((EFI_D_ERROR,
97               "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
98               __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
99           } else {
100             DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
101               __FUNCTION__, CurBase, CurBase + CurSize - 1));
102           }
103         }
104       }
105     }
106   }
107 
108   return EFI_SUCCESS;
109 }
110