summaryrefslogtreecommitdiff
path: root/ArmVirtPkg/PrePi/FdtParser.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmVirtPkg/PrePi/FdtParser.c')
-rw-r--r--ArmVirtPkg/PrePi/FdtParser.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/ArmVirtPkg/PrePi/FdtParser.c b/ArmVirtPkg/PrePi/FdtParser.c
new file mode 100644
index 0000000..afdc81a
--- /dev/null
+++ b/ArmVirtPkg/PrePi/FdtParser.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ *
+ * This program and the accompanying materials
+ * are licensed and made available under the terms and conditions of the BSD License
+ * which accompanies this distribution. The full text of the license may be found at
+ * http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ */
+
+#include <Uefi.h>
+#include <Include/libfdt.h>
+
+BOOLEAN
+FindMemnode (
+ IN VOID *DeviceTreeBlob,
+ OUT UINT64 *SystemMemoryBase,
+ OUT UINT64 *SystemMemorySize
+ )
+{
+ INT32 MemoryNode;
+ INT32 AddressCells;
+ INT32 SizeCells;
+ INT32 Length;
+ CONST INT32 *Prop;
+
+ if (fdt_check_header (DeviceTreeBlob) != 0) {
+ return FALSE;
+ }
+
+ //
+ // Look for a node called "memory" at the lowest level of the tree
+ //
+ MemoryNode = fdt_path_offset (DeviceTreeBlob, "/memory");
+ if (MemoryNode <= 0) {
+ return FALSE;
+ }
+
+ //
+ // Retrieve the #address-cells and #size-cells properties
+ // from the root node, or use the default if not provided.
+ //
+ AddressCells = 1;
+ SizeCells = 1;
+
+ Prop = fdt_getprop (DeviceTreeBlob, 0, "#address-cells", &Length);
+ if (Length == 4) {
+ AddressCells = fdt32_to_cpu (*Prop);
+ }
+
+ Prop = fdt_getprop (DeviceTreeBlob, 0, "#size-cells", &Length);
+ if (Length == 4) {
+ SizeCells = fdt32_to_cpu (*Prop);
+ }
+
+ //
+ // Now find the 'reg' property of the /memory node, and read the first
+ // range listed.
+ //
+ Prop = fdt_getprop (DeviceTreeBlob, MemoryNode, "reg", &Length);
+
+ if (Length < (AddressCells + SizeCells) * sizeof (INT32)) {
+ return FALSE;
+ }
+
+ *SystemMemoryBase = fdt32_to_cpu (Prop[0]);
+ if (AddressCells > 1) {
+ *SystemMemoryBase = (*SystemMemoryBase << 32) | fdt32_to_cpu (Prop[1]);
+ }
+ Prop += AddressCells;
+
+ *SystemMemorySize = fdt32_to_cpu (Prop[0]);
+ if (SizeCells > 1) {
+ *SystemMemorySize = (*SystemMemorySize << 32) | fdt32_to_cpu (Prop[1]);
+ }
+
+ return TRUE;
+}
+
+VOID
+CopyFdt (
+ IN VOID *FdtDest,
+ IN VOID *FdtSource
+ )
+{
+ fdt_pack(FdtSource);
+ CopyMem (FdtDest, FdtSource, fdt_totalsize (FdtSource));
+}