]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoPeiLibConstructor.c
ArmVirtPkg/ArmVirtQemu*: enable minimal Status Code Routing in DXE
[mirror_edk2.git] / ArmVirtPkg / Library / QemuVirtMemInfoLib / QemuVirtMemInfoPeiLibConstructor.c
1 /** @file
2
3 Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
4
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Base.h>
16 #include <Library/DebugLib.h>
17 #include <Library/PcdLib.h>
18 #include <libfdt.h>
19
20 RETURN_STATUS
21 EFIAPI
22 QemuVirtMemInfoPeiLibConstructor (
23 VOID
24 )
25 {
26 VOID *DeviceTreeBase;
27 INT32 Node, Prev;
28 UINT64 NewBase, CurBase;
29 UINT64 NewSize, CurSize;
30 CONST CHAR8 *Type;
31 INT32 Len;
32 CONST UINT64 *RegProp;
33 RETURN_STATUS PcdStatus;
34
35 NewBase = 0;
36 NewSize = 0;
37
38 DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
39 ASSERT (DeviceTreeBase != NULL);
40
41 //
42 // Make sure we have a valid device tree blob
43 //
44 ASSERT (fdt_check_header (DeviceTreeBase) == 0);
45
46 //
47 // Look for the lowest memory node
48 //
49 for (Prev = 0;; Prev = Node) {
50 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
51 if (Node < 0) {
52 break;
53 }
54
55 //
56 // Check for memory node
57 //
58 Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
59 if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
60 //
61 // Get the 'reg' property of this node. For now, we will assume
62 // two 8 byte quantities for base and size, respectively.
63 //
64 RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
65 if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {
66
67 CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
68 CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
69
70 DEBUG ((DEBUG_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n",
71 __FUNCTION__, CurBase, CurBase + CurSize - 1));
72
73 if (NewBase > CurBase || NewBase == 0) {
74 NewBase = CurBase;
75 NewSize = CurSize;
76 }
77 } else {
78 DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT memory node\n",
79 __FUNCTION__));
80 }
81 }
82 }
83
84 //
85 // Make sure the start of DRAM matches our expectation
86 //
87 ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase);
88 PcdStatus = PcdSet64S (PcdSystemMemorySize, NewSize);
89 ASSERT_RETURN_ERROR (PcdStatus);
90
91 //
92 // We need to make sure that the machine we are running on has at least
93 // 128 MB of memory configured, and is currently executing this binary from
94 // NOR flash. This prevents a device tree image in DRAM from getting
95 // clobbered when our caller installs permanent PEI RAM, before we have a
96 // chance of marking its location as reserved or copy it to a freshly
97 // allocated block in the permanent PEI RAM in the platform PEIM.
98 //
99 ASSERT (NewSize >= SIZE_128MB);
100 ASSERT (
101 (((UINT64)PcdGet64 (PcdFdBaseAddress) +
102 (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) ||
103 ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize)));
104
105 return RETURN_SUCCESS;
106 }