summaryrefslogtreecommitdiffstats
path: root/EmbeddedPkg/Library
diff options
context:
space:
mode:
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>2012-09-27 16:53:57 +0000
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>2012-09-27 16:53:57 +0000
commitfa4a70633868ce5a59e3bc3c98c137952a6c4ccb (patch)
treec29d5d77b7b05b194377b77c068147cc6cc09f5d /EmbeddedPkg/Library
parent8213627ef73ea5cac96c9eaeaed8dd8169ec3431 (diff)
downloadedk2-fa4a70633868ce5a59e3bc3c98c137952a6c4ccb.tar.gz
edk2-fa4a70633868ce5a59e3bc3c98c137952a6c4ccb.tar.bz2
edk2-fa4a70633868ce5a59e3bc3c98c137952a6c4ccb.zip
EmbeddedPkg: Added support to libfdt
Use the library libdt from the Device Tree Compiler project. The used version is from Wednesday 22nd August 2012 (commit: 8716901d2215a3) The Device Tree Compiler project is under dual BSD/GPL license (it means the license is either BSD or GPL). The BSD license is the license that fits to the Tianocore contribution requirements. The use of libfdt into Tianocore has been authorised by David Gibson the author of libfdt and its current maintainer Jon Loeliger (email thread on 7th September 2011). Signed-off-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13760 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EmbeddedPkg/Library')
-rw-r--r--EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch220
-rw-r--r--EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch489
-rw-r--r--EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch300
-rw-r--r--EmbeddedPkg/Library/FdtLib/FdtLib.inf38
-rw-r--r--EmbeddedPkg/Library/FdtLib/Makefile.libfdt10
-rw-r--r--EmbeddedPkg/Library/FdtLib/TODO3
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt.c222
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c84
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_ro.c575
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_rw.c495
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_strerror.c96
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_sw.c256
-rw-r--r--EmbeddedPkg/Library/FdtLib/fdt_wip.c118
-rw-r--r--EmbeddedPkg/Library/FdtLib/libfdt_internal.h95
-rw-r--r--EmbeddedPkg/Library/FdtLib/version.lds54
15 files changed, 2046 insertions, 1009 deletions
diff --git a/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch b/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch
deleted file mode 100644
index ae06b6f396..0000000000
--- a/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch
+++ /dev/null
@@ -1,220 +0,0 @@
-From 669778eab2092ef85ed5b5e537203721cfb1215d Mon Sep 17 00:00:00 2001
-From: Olivier Martin <olivier.martin@arm.com>
-Date: Thu, 16 Feb 2012 15:44:35 +0000
-Subject: [PATCH 1/3] EmbeddedPkg: Added libfdt port
-
-This port is based on the 'libfdt' project (dual licensed BSD/GPL).
-
-Prior to apply this patch you must execute the following steps:
-
-1. Clone the dtc into a temporary directory:
-cd EmbeddedPkg/Library
-git clone git://git.jdl.com/software/dtc.git
-
-2. Copy the content of 'libfdt' into EmbeddedPkg/Library/FdtLib/
-cd dtc
-cp -a libfdt ../FdtLib
-
-3. Copy the libfdt headers:
-mv ../FdtLib/libfdt.h ../../Include/
-mv ../FdtLib/fdt.h ../../Include/
-rm ../FdtLib/libfdt_env.h
----
- EmbeddedPkg/EmbeddedPkg.dsc | 1 +
- EmbeddedPkg/Include/libfdt_env.h | 77 +++++++++++++++++++++++++++++++++
- EmbeddedPkg/Library/FdtLib/FdtLib.inf | 38 ++++++++++++++++
- EmbeddedPkg/Library/FdtLib/README.txt | 38 ++++++++++++++++
- 4 files changed, 154 insertions(+), 0 deletions(-)
- mode change 100644 => 100755 EmbeddedPkg/EmbeddedPkg.dsc
- create mode 100755 EmbeddedPkg/Include/libfdt_env.h
- create mode 100755 EmbeddedPkg/Library/FdtLib/FdtLib.inf
- create mode 100755 EmbeddedPkg/Library/FdtLib/README.txt
-
-diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc
-old mode 100644
-new mode 100755
-index 8862f3d..c3a2464
---- a/EmbeddedPkg/EmbeddedPkg.dsc
-+++ b/EmbeddedPkg/EmbeddedPkg.dsc
-@@ -97,6 +97,7 @@
-
- EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf
-
-+ FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
-
- [LibraryClasses.common.DXE_DRIVER]
- PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
-diff --git a/EmbeddedPkg/Include/libfdt_env.h b/EmbeddedPkg/Include/libfdt_env.h
-new file mode 100755
-index 0000000..8c4f1c7
---- /dev/null
-+++ b/EmbeddedPkg/Include/libfdt_env.h
-@@ -0,0 +1,77 @@
-+/** @file
-+*
-+* Copyright (c) 2011, ARM Limited. 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.
-+*
-+**/
-+
-+#ifndef _LIBFDT_ENV_H
-+#define _LIBFDT_ENV_H
-+
-+#include <Library/BaseLib.h>
-+#include <Library/BaseMemoryLib.h>
-+
-+typedef UINT8 uint8_t;
-+typedef UINT16 uint16_t;
-+typedef UINT32 uint32_t;
-+typedef UINT64 uint64_t;
-+typedef UINTN uintptr_t;
-+typedef UINTN size_t;
-+
-+static inline uint16_t fdt16_to_cpu(uint16_t x)
-+{
-+ return SwapBytes16 (x);
-+}
-+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
-+
-+static inline uint32_t fdt32_to_cpu(uint32_t x)
-+{
-+ return SwapBytes32 (x);
-+}
-+#define cpu_to_fdt32(x) fdt32_to_cpu(x)
-+
-+static inline uint64_t fdt64_to_cpu(uint64_t x)
-+{
-+ return SwapBytes64 (x);
-+}
-+#define cpu_to_fdt64(x) fdt64_to_cpu(x)
-+
-+static inline void* memcpy(void* dest, const void* src, size_t len) {
-+ return CopyMem (dest, src, len);
-+}
-+
-+static inline void *memmove(void *dest, const void *src, size_t n) {
-+ return CopyMem (dest, src, n);
-+}
-+
-+static inline void *memset(void *s, int c, size_t n) {
-+ return SetMem (s, n, c);
-+}
-+
-+static inline int memcmp(const void* dest, const void* src, int len) {
-+ return CompareMem (dest, src, len);
-+}
-+
-+static inline void *memchr(const void *s, int c, size_t n) {
-+ return ScanMem8 (s, n, c);
-+}
-+
-+static inline size_t strlen (const char* str) {
-+ return AsciiStrLen (str);
-+}
-+
-+static inline char *strchr(const char *s, int c) {
-+ char pattern[2];
-+ pattern[0] = c;
-+ pattern[1] = 0;
-+ return AsciiStrStr (s, pattern);
-+}
-+
-+#endif /* _LIBFDT_ENV_H */
-diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
-new file mode 100755
-index 0000000..9753ed8
---- /dev/null
-+++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
-@@ -0,0 +1,38 @@
-+#/* @file
-+# Copyright (c) 2011, ARM Limited. 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.
-+#
-+#*/
-+
-+[Defines]
-+ INF_VERSION = 0x00010005
-+ BASE_NAME = FdtLib
-+ FILE_GUID = 6b2478c0-be23-11e0-a28c-0002a5d5c51b
-+ MODULE_TYPE = BASE
-+ VERSION_STRING = 1.0
-+ LIBRARY_CLASS = FdtLib
-+
-+#
-+# The following information is for reference only and not required by the build tools.
-+#
-+# VALID_ARCHITECTURES = ARM
-+#
-+
-+[Sources]
-+ fdt_ro.c
-+ fdt_rw.c
-+ fdt_strerror.c
-+ fdt_sw.c
-+ fdt_wip.c
-+ fdt.c
-+
-+[Packages]
-+ MdePkg/MdePkg.dec
-+ EmbeddedPkg/EmbeddedPkg.dec
-diff --git a/EmbeddedPkg/Library/FdtLib/README.txt b/EmbeddedPkg/Library/FdtLib/README.txt
-new file mode 100755
-index 0000000..c74db7a
---- /dev/null
-+++ b/EmbeddedPkg/Library/FdtLib/README.txt
-@@ -0,0 +1,38 @@
-+Credits
-+-------
-+Principal original author: David Gibson (david AT gibson.dropbear.id.au)
-+Maintainer: Jon Loeliger (jdl AT jdl.com)
-+
-+
-+Licensing:
-+----------
-+libfdt is GPL/BSD dual-licensed.
-+
-+
-+Current version:
-+----------------
-+
-+# Latest commit in dtc.git repository :
-+commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86
-+Author: Minghuan Lian <Minghuan.Lian@freescale.com>
-+Date: Mon Dec 5 12:22:07 2011 +1100
-+
-+# Latest commit in libfdt :
-+commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86
-+Author: Minghuan Lian <Minghuan.Lian@freescale.com>
-+Date: Mon Dec 5 12:22:07 2011 +1100
-+
-+
-+How to update EmbeddedPkg/Library/FdtLib
-+----------------------------------------
-+1. Clone the dtc into a temporary directory:
-+git clone git://git.jdl.com/software/dtc.git
-+
-+2. Copy the content of 'libfdt' into EmbeddedPkg/Library/FdtLib/
-+cd dtc
-+cp -a libfdt/* $(EDK2_ROOT)/EmbeddedPkg/Library/FdtLib/
-+
-+3. Copy the libfdt headers:
-+mv $(EDK2_ROOT)/EmbeddedPkg/Library/FdtLib/libfdt.h $(EDK2_ROOT)/EmbeddedPkg/Include/
-+mv $(EDK2_ROOT)/EmbeddedPkg/Library/FdtLib/fdt.h $(EDK2_ROOT)/EmbeddedPkg/Include/
-+rm $(EDK2_ROOT)/EmbeddedPkg/Library/FdtLib/libfdt_env.h
---
-1.7.0.4
-
diff --git a/EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch b/EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch
deleted file mode 100644
index 66ea902875..0000000000
--- a/EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch
+++ /dev/null
@@ -1,489 +0,0 @@
-From 9c16a23fba659cdf0ce798aa085a4fb8c3bd47d1 Mon Sep 17 00:00:00 2001
-From: Olivier Martin <olivier.martin@arm.com>
-Date: Thu, 16 Feb 2012 15:50:59 +0000
-Subject: [PATCH 2/3] ArmPkg/BdsLib: Added support for modifying the passed FDT blob
-
-- Add Linux CmdLine if not defined
-- Add initrd if not defined
-- Add CPU parking address if not defined
-- Add System Memory info if not defined
----
- ArmPkg/ArmPkg.dsc | 1 +
- ArmPkg/Library/BdsLib/BdsInternal.h | 9 +
- ArmPkg/Library/BdsLib/BdsLib.inf | 3 +
- ArmPkg/Library/BdsLib/BdsLinuxFdt.c | 353 ++++++++++++++++++++++++++++++++
- ArmPkg/Library/BdsLib/BdsLinuxLoader.c | 8 +
- ArmPkg/Library/BdsLib/BdsLinuxLoader.h | 10 +-
- 6 files changed, 383 insertions(+), 1 deletions(-)
- mode change 100644 => 100755 ArmPkg/ArmPkg.dsc
- mode change 100644 => 100755 ArmPkg/Library/BdsLib/BdsInternal.h
- mode change 100644 => 100755 ArmPkg/Library/BdsLib/BdsLib.inf
- create mode 100755 ArmPkg/Library/BdsLib/BdsLinuxFdt.c
-
-diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
-old mode 100644
-new mode 100755
-index f4989a6..07c825d
---- a/ArmPkg/ArmPkg.dsc
-+++ b/ArmPkg/ArmPkg.dsc
-@@ -72,6 +72,7 @@
- SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
-
- BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf
-+ FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
-
- IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-
-diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h
-old mode 100644
-new mode 100755
-index 880d780..80d21b2
---- a/ArmPkg/Library/BdsLib/BdsInternal.h
-+++ b/ArmPkg/Library/BdsLib/BdsInternal.h
-@@ -103,4 +103,13 @@ PrepareAtagList (
- OUT UINT32 *AtagSize
- );
-
-+EFI_STATUS
-+PrepareFdt (
-+ IN CONST CHAR8* CommandLineString,
-+ IN EFI_PHYSICAL_ADDRESS InitrdImage,
-+ IN UINTN InitrdImageSize,
-+ IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,
-+ IN OUT UINT32 *FdtBlobSize
-+ );
-+
- #endif
-diff --git a/ArmPkg/Library/BdsLib/BdsLib.inf b/ArmPkg/Library/BdsLib/BdsLib.inf
-old mode 100644
-new mode 100755
-index 20644f1..b3cab21
---- a/ArmPkg/Library/BdsLib/BdsLib.inf
-+++ b/ArmPkg/Library/BdsLib/BdsLib.inf
-@@ -27,6 +27,7 @@
-
- BdsLinuxLoader.c
- BdsLinuxAtag.c
-+ BdsLinuxFdt.c
-
- [Packages]
- MdePkg/MdePkg.dec
-@@ -41,9 +42,11 @@
- HobLib
- PerformanceLib
- SerialPortLib
-+ FdtLib
-
- [Guids]
- gEfiFileInfoGuid
-+ gArmMpCoreInfoGuid
-
- [Protocols]
- gEfiBdsArchProtocolGuid
-diff --git a/ArmPkg/Library/BdsLib/BdsLinuxFdt.c b/ArmPkg/Library/BdsLib/BdsLinuxFdt.c
-new file mode 100755
-index 0000000..5c14b65
---- /dev/null
-+++ b/ArmPkg/Library/BdsLib/BdsLinuxFdt.c
-@@ -0,0 +1,353 @@
-+/** @file
-+*
-+* Copyright (c) 2011-2012, ARM Limited. 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 <Library/PcdLib.h>
-+#include <libfdt.h>
-+
-+#include "BdsInternal.h"
-+
-+#define LINUX_FDT_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))
-+
-+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-+#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
-+#define GET_CELL(p) (p += 4, *((const UINT32 *)(p-4)))
-+
-+STATIC
-+UINTN
-+IsPrintableString (
-+ IN CONST VOID* data,
-+ IN UINTN len
-+ )
-+{
-+ CONST CHAR8 *s = data;
-+ CONST CHAR8 *ss;
-+
-+ // zero length is not
-+ if (len == 0) {
-+ return 0;
-+ }
-+
-+ // must terminate with zero
-+ if (s[len - 1] != '\0') {
-+ return 0;
-+ }
-+
-+ ss = s;
-+ while (*s/* && isprint(*s)*/) {
-+ s++;
-+ }
-+
-+ // not zero, or not done yet
-+ if (*s != '\0' || (s + 1 - ss) < len) {
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+STATIC
-+VOID
-+PrintData (
-+ IN CONST CHAR8* data,
-+ IN UINTN len
-+ )
-+{
-+ UINTN i;
-+ CONST CHAR8 *p = data;
-+
-+ // no data, don't print
-+ if (len == 0)
-+ return;
-+
-+ if (IsPrintableString (data, len)) {
-+ Print(L" = \"%a\"", (const char *)data);
-+ } else if ((len % 4) == 0) {
-+ Print(L" = <");
-+ for (i = 0; i < len; i += 4) {
-+ Print(L"0x%08x%a", fdt32_to_cpu(GET_CELL(p)),i < (len - 4) ? " " : "");
-+ }
-+ Print(L">");
-+ } else {
-+ Print(L" = [");
-+ for (i = 0; i < len; i++)
-+ Print(L"%02x%a", *p++, i < len - 1 ? " " : "");
-+ Print(L"]");
-+ }
-+}
-+
-+VOID
-+DebugDumpFdt (
-+ IN VOID* FdtBlob
-+ )
-+{
-+ struct fdt_header *bph;
-+ UINT32 off_dt;
-+ UINT32 off_str;
-+ CONST CHAR8* p_struct;
-+ CONST CHAR8* p_strings;
-+ CONST CHAR8* p;
-+ CONST CHAR8* s;
-+ CONST CHAR8* t;
-+ UINT32 tag;
-+ UINTN sz;
-+ UINTN depth;
-+ UINTN shift;
-+ UINT32 version;
-+
-+ depth = 0;
-+ shift = 4;
-+
-+ bph = FdtBlob;
-+ off_dt = fdt32_to_cpu(bph->off_dt_struct);
-+ off_str = fdt32_to_cpu(bph->off_dt_strings);
-+ p_struct = (CONST CHAR8*)FdtBlob + off_dt;
-+ p_strings = (CONST CHAR8*)FdtBlob + off_str;
-+ version = fdt32_to_cpu(bph->version);
-+
-+ p = p_struct;
-+ while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
-+
-+ //printf("tag: 0x%08x (%d)\n", tag, p - p_struct);
-+
-+ if (tag == FDT_BEGIN_NODE) {
-+ s = p;
-+ p = PALIGN(p + AsciiStrLen (s) + 1, 4);
-+
-+ if (*s == '\0')
-+ s = "/";
-+
-+ Print(L"%*s%a {\n", depth * shift, L" ", s);
-+
-+ depth++;
-+ continue;
-+ }
-+
-+ if (tag == FDT_END_NODE) {
-+ depth--;
-+
-+ Print(L"%*s};\n", depth * shift, L" ");
-+ continue;
-+ }
-+
-+ if (tag == FDT_NOP) {
-+ Print(L"%*s// [NOP]\n", depth * shift, L" ");
-+ continue;
-+ }
-+
-+ if (tag != FDT_PROP) {
-+ Print(L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag);
-+ break;
-+ }
-+ sz = fdt32_to_cpu(GET_CELL(p));
-+ s = p_strings + fdt32_to_cpu(GET_CELL(p));
-+ if (version < 16 && sz >= 8)
-+ p = PALIGN(p, 8);
-+ t = p;
-+
-+ p = PALIGN(p + sz, 4);
-+
-+ Print(L"%*s%a", depth * shift, L" ", s);
-+ PrintData(t, sz);
-+ Print(L";\n");
-+ }
-+}
-+
-+typedef struct {
-+ UINTN Base;
-+ UINTN Size;
-+} FdtRegion;
-+
-+EFI_STATUS
-+PrepareFdt (
-+ IN CONST CHAR8* CommandLineString,
-+ IN EFI_PHYSICAL_ADDRESS InitrdImage,
-+ IN UINTN InitrdImageSize,
-+ IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,
-+ IN OUT UINT32 *FdtBlobSize
-+ )
-+{
-+ EFI_STATUS Status;
-+ EFI_PHYSICAL_ADDRESS NewFdtBlobBase;
-+ UINTN NewFdtBlobSize;
-+ VOID* fdt;
-+ INTN err;
-+ INTN node;
-+ INTN cpu_node;
-+ INTN lenp;
-+ CONST VOID* BootArg;
-+ EFI_PHYSICAL_ADDRESS InitrdImageStart;
-+ EFI_PHYSICAL_ADDRESS InitrdImageEnd;
-+ FdtRegion Region;
-+ UINTN Index;
-+ CHAR8 Name[10];
-+ LIST_ENTRY ResourceList;
-+ BDS_SYSTEM_MEMORY_RESOURCE *Resource;
-+ ARM_PROCESSOR_TABLE *ArmProcessorTable;
-+ ARM_CORE_INFO *ArmCoreInfoTable;
-+ UINT32 MpId;
-+ UINT32 ClusterId;
-+ UINT32 CoreId;
-+ UINT64 CpuReleaseAddr;
-+
-+ err = fdt_check_header ((VOID*)(UINTN)(*FdtBlobBase));
-+ if (err != 0) {
-+ Print (L"ERROR: Device Tree header not valid (err:%d)\n", err);
-+ return EFI_INVALID_PARAMETER;
-+ }
-+
-+ // Allocate memory for the new FDT
-+ NewFdtBlobBase = LINUX_FDT_MAX_OFFSET;
-+ NewFdtBlobSize = *FdtBlobSize + FDT_ADDITIONAL_ENTRIES_SIZE;
-+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
-+ if (EFI_ERROR(Status)) {
-+ DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Fdt below 0x%lX (%r). The Fdt will be allocated somewhere else in System Memory.\n",NewFdtBlobBase,Status));
-+ Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
-+ ASSERT_EFI_ERROR(Status);
-+ goto FAIL_NEW_FDT;
-+ }
-+
-+ // Load the Original FDT tree into the new region
-+ fdt = (VOID*)(UINTN)NewFdtBlobBase;
-+ err = fdt_open_into((VOID*)(UINTN)(*FdtBlobBase), fdt, NewFdtBlobSize);
-+ if (err) {
-+ DEBUG((EFI_D_ERROR, "fdt_open_into(): %a\n", fdt_strerror(err)));
-+ Status = EFI_INVALID_PARAMETER;
-+ goto FAIL_NEW_FDT;
-+ }
-+
-+ DEBUG_CODE_BEGIN();
-+ DebugDumpFdt (fdt);
-+ DEBUG_CODE_END();
-+
-+ node = fdt_subnode_offset(fdt, 0, "chosen");
-+ if (node < 0) {
-+ // The 'chosen' node does not exist, create it
-+ node = fdt_add_subnode(fdt, 0, "chosen");
-+ if (node < 0) {
-+ DEBUG((EFI_D_ERROR,"Error on finding 'chosen' node\n"));
-+ Status = EFI_INVALID_PARAMETER;
-+ goto FAIL_NEW_FDT;
-+ }
-+ }
-+
-+ DEBUG_CODE_BEGIN();
-+ BootArg = fdt_getprop(fdt, node, "bootargs", &lenp);
-+ if (BootArg != NULL) {
-+ DEBUG((EFI_D_ERROR,"BootArg: %a\n",BootArg));
-+ }
-+ DEBUG_CODE_END();
-+
-+ // Set Linux CmdLine
-+ if ((CommandLineString != NULL) && (AsciiStrLen (CommandLineString) > 0)) {
-+ err = fdt_setprop(fdt, node, "bootargs", CommandLineString, AsciiStrSize(CommandLineString));
-+ if (err) {
-+ DEBUG((EFI_D_ERROR,"Fail to set new 'bootarg' (err:%d)\n",err));
-+ }
-+ }
-+
-+ // Set Linux Initrd
-+ if (InitrdImageSize != 0) {
-+ InitrdImageStart = cpu_to_fdt64 (InitrdImage);
-+ err = fdt_setprop(fdt, node, "linux,initrd-start", &InitrdImageStart, sizeof(EFI_PHYSICAL_ADDRESS));
-+ if (err) {
-+ DEBUG((EFI_D_ERROR,"Fail to set new 'linux,initrd-start' (err:%d)\n",err));
-+ }
-+ InitrdImageEnd = cpu_to_fdt64 (InitrdImage + InitrdImageSize);
-+ err = fdt_setprop(fdt, node, "linux,initrd-end", &InitrdImageEnd, sizeof(EFI_PHYSICAL_ADDRESS));
-+ if (err) {
-+ DEBUG((EFI_D_ERROR,"Fail to set new 'linux,initrd-start' (err:%d)\n",err));
-+ }
-+ }
-+
-+ // Set Physical memory setup if does not exist
-+ node = fdt_subnode_offset(fdt, 0, "memory");
-+ if (node < 0) {
-+ // The 'chosen' node does not exist, create it
-+ node = fdt_add_subnode(fdt, 0, "memory");
-+ if (node >= 0) {
-+ fdt_setprop_string(fdt, node, "name", "memory");
-+ fdt_setprop_string(fdt, node, "device_type", "memory");
-+
-+ GetSystemMemoryResources (&ResourceList);
-+ Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceList.ForwardLink;
-+
-+ if (sizeof(UINTN) == sizeof(UINT32)) {
-+ Region.Base = cpu_to_fdt32((UINTN)Resource->PhysicalStart);
-+ Region.Size = cpu_to_fdt32((UINTN)Resource->ResourceLength);
-+ } else {
-+ Region.Base = cpu_to_fdt64((UINTN)Resource->PhysicalStart);
-+ Region.Size = cpu_to_fdt64((UINTN)Resource->ResourceLength);
-+ }
-+
-+ err = fdt_setprop(fdt, node, "reg", &Region, sizeof(Region));
-+ if (err) {
-+ DEBUG((EFI_D_ERROR,"Fail to set new 'memory region' (err:%d)\n",err));
-+ }
-+ }
-+ }
-+
-+ // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms
-+ for (Index=0; Index < gST->NumberOfTableEntries; Index++) {
-+ // Check for correct GUID type
-+ if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
-+ MpId = ArmReadMpidr ();
-+ ClusterId = GET_CLUSTER_ID(MpId);
-+ CoreId = GET_CORE_ID(MpId);
-+
-+ node = fdt_subnode_offset(fdt, 0, "cpus");
-+ if (node < 0) {
-+ // Create the /cpus node
-+ node = fdt_add_subnode(fdt, 0, "cpus");
-+ fdt_setprop_string(fdt, node, "name", "cpus");
-+ fdt_setprop_cell(fdt, node, "#address-cells", 1);
-+ fdt_setprop_cell(fdt, node, "#size-cells", 0);
-+ }
-+
-+ // Get pointer to ARM processor table
-+ ArmProcessorTable = (ARM_PROCESSOR_TABLE *)gST->ConfigurationTable[Index].VendorTable;
-+ ArmCoreInfoTable = ArmProcessorTable->ArmCpus;
-+
-+ for (Index = 0; Index < ArmProcessorTable->NumberOfEntries; Index++) {
-+ if (((ArmCoreInfoTable[Index].ClusterId != ClusterId) || (ArmCoreInfoTable[Index].CoreId != CoreId))) {
-+ AsciiSPrint (Name, 10, "cpu@%d", Index);
-+ cpu_node = fdt_subnode_offset(fdt, node, Name);
-+ if (cpu_node < 0) {
-+ cpu_node = fdt_add_subnode(fdt, node, Name);
-+ }
-+ fdt_setprop_string(fdt, cpu_node, "device-type", "cpu");
-+ fdt_setprop_string(fdt, cpu_node, "enable-method", "spin-table");
-+ fdt_setprop_string(fdt, cpu_node, "status", "disabled");
-+ CpuReleaseAddr = cpu_to_fdt64(ArmCoreInfoTable[Index].MailboxSetAddress);
-+ fdt_setprop(fdt, cpu_node, "cpu-release-addr", &CpuReleaseAddr, sizeof(CpuReleaseAddr));
-+ }
-+ }
-+ break;
-+ }
-+ }
-+
-+ DEBUG_CODE_BEGIN();
-+ DebugDumpFdt (fdt);
-+ DEBUG_CODE_END();
-+
-+ *FdtBlobBase = NewFdtBlobBase;
-+ *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));;
-+ return EFI_SUCCESS;
-+
-+FAIL_NEW_FDT:
-+ *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(*FdtBlobBase));
-+ // Return success even if we failed to update the FDT blob. The original one is still valid.
-+ return EFI_SUCCESS;
-+}
-+
-+
-diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
-index 12a8862..82fa811 100755
---- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
-+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c
-@@ -241,6 +241,14 @@ BdsBootLinuxFdt (
- Print (L"ERROR: Did not find Device Tree blob.\n");
- return Status;
- }
-+
-+ // By setting address=0 we leave the memory allocation to the function
-+ Status = PrepareFdt (Arguments, InitrdImage, InitrdImageSize, &KernelParamsAddress, &KernelParamsSize);
-+ if (EFI_ERROR(Status)) {
-+ Print(L"ERROR: Can not load Linux kernel with Device Tree. Status=0x%X\n", Status);
-+ return Status;
-+ }
-+
- return StartLinux (LinuxImage, LinuxImageSize, KernelParamsAddress, KernelParamsSize, FdtMachineType);
- }
-
-diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
-index 8d58ce1..9e45e03 100755
---- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
-+++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h
-@@ -15,12 +15,20 @@
- #ifndef __BDSLINUXLOADER_H
- #define __BDSLINUXLOADER_H
-
-+#include <Guid/ArmMpCoreInfo.h>
-+
- #define LINUX_UIMAGE_SIGNATURE 0x56190527
-
- #define LINUX_ATAG_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))
- #define LINUX_KERNEL_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset))
-
--#define ATAG_MAX_SIZE 0x3000
-+// Size allocated for the Atag list
-+#define ATAG_MAX_SIZE 0x3000
-+
-+// Additional size that could be used for FDT entries added by the UEFI OS Loader
-+// Estimation based on: EDID (300bytes) + bootargs (200bytes) + initrd region (20bytes)
-+// + system memory region (20bytes) + mp_core entries (200 bytes)
-+#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300
-
- /* ATAG : list of possible tags */
- #define ATAG_NONE 0x00000000
---
-1.7.0.4
-
diff --git a/EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch b/EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch
deleted file mode 100644
index 98fc8fcb13..0000000000
--- a/EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch
+++ /dev/null
@@ -1,300 +0,0 @@
-From 82540f3a4b280133f2d1a58cb8baba01c1f09690 Mon Sep 17 00:00:00 2001
-From: Olivier Martin <olivier.martin@arm.com>
-Date: Thu, 16 Feb 2012 15:56:40 +0000
-Subject: [PATCH 3/3] ArmPlatformPkg/EblCmdLib: Add 'dumpfdt' EBL command
-
-This command dumps the FDT blob pointed by the Device Path defined in the
-command argument or used the Platform specifc FDT defined by its Device Path
-in the UEFI Variable 'Fdt' or the PcdFdtDevicePath PCD.
----
- ArmPlatformPkg/Library/EblCmdLib/EblCmdFdt.c | 206 ++++++++++++++++++++++++
- ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c | 12 ++
- ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf | 6 +
- 3 files changed, 224 insertions(+), 0 deletions(-)
- create mode 100755 ArmPlatformPkg/Library/EblCmdLib/EblCmdFdt.c
- mode change 100644 => 100755 ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
- mode change 100644 => 100755 ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf
-
-diff --git a/ArmPlatformPkg/Library/EblCmdLib/EblCmdFdt.c b/ArmPlatformPkg/Library/EblCmdLib/EblCmdFdt.c
-new file mode 100755
-index 0000000..3c5eb8e
---- /dev/null
-+++ b/ArmPlatformPkg/Library/EblCmdLib/EblCmdFdt.c
-@@ -0,0 +1,206 @@
-+#include <Base.h>
-+#include <Uefi.h>
-+#include <Library/MemoryAllocationLib.h>
-+#include <Library/BdsLib.h>
-+#include <Library/DebugLib.h>
-+#include <Library/PcdLib.h>
-+#include <Library/PrintLib.h>
-+#include <Library/UefiLib.h>
-+#include <Library/UefiApplicationEntryPoint.h>
-+#include <Library/UefiBootServicesTableLib.h>
-+#include <Library/UefiRuntimeServicesTableLib.h>
-+
-+#include <Protocol/DevicePathFromText.h>
-+
-+#include <Guid/GlobalVariable.h>
-+
-+#include <libfdt.h>
-+
-+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-+#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
-+#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
-+
-+STATIC
-+UINTN
-+IsPrintableString (
-+ IN CONST VOID* data,
-+ IN UINTN len
-+ )
-+{
-+ CONST CHAR8 *s = data;
-+ CONST CHAR8 *ss;
-+
-+ /* zero length is not */
-+ if (len == 0) {
-+ return 0;
-+ }
-+
-+ /* must terminate with zero */
-+ if (s[len - 1] != '\0') {
-+ return 0;
-+ }
-+
-+ ss = s;
-+ while (*s/* && isprint(*s)*/) {
-+ s++;
-+ }
-+
-+ /* not zero, or not done yet */
-+ if (*s != '\0' || (s + 1 - ss) < len) {
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+STATIC
-+VOID
-+PrintData (
-+ IN CONST CHAR8* data,
-+ IN UINTN len
-+ )
-+{
-+ UINTN i;
-+ CONST CHAR8 *p = data;
-+
-+ /* no data, don't print */
-+ if (len == 0)
-+ return;
-+
-+ if (IsPrintableString (data, len)) {
-+ Print(L" = \"%a\"", (const char *)data);
-+ } else if ((len % 4) == 0) {
-+ Print(L" = <");
-+ for (i = 0; i < len; i += 4) {
-+ Print(L"0x%08x%a", fdt32_to_cpu(GET_CELL(p)),i < (len - 4) ? " " : "");
-+ }
-+ Print(L">");
-+ } else {
-+ Print(L" = [");
-+ for (i = 0; i < len; i++)
-+ Print(L"%02x%a", *p++, i < len - 1 ? " " : "");
-+ Print(L"]");
-+ }
-+}
-+
-+VOID
-+DumpFdt (
-+ IN VOID* FdtBlob
-+ )
-+{
-+ struct fdt_header *bph;
-+ UINT32 off_dt;
-+ UINT32 off_str;
-+ CONST CHAR8* p_struct;
-+ CONST CHAR8* p_strings;
-+ CONST CHAR8* p;
-+ CONST CHAR8* s;
-+ CONST CHAR8* t;
-+ UINT32 tag;
-+ UINTN sz;
-+ UINTN depth;
-+ UINTN shift;
-+ UINT32 version;
-+
-+ depth = 0;
-+ shift = 4;
-+
-+ bph = FdtBlob;
-+ off_dt = fdt32_to_cpu(bph->off_dt_struct);
-+ off_str = fdt32_to_cpu(bph->off_dt_strings);
-+ p_struct = (CONST CHAR8*)FdtBlob + off_dt;
-+ p_strings = (CONST CHAR8*)FdtBlob + off_str;
-+ version = fdt32_to_cpu(bph->version);
-+
-+ p = p_struct;
-+ while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
-+
-+ /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
-+
-+ if (tag == FDT_BEGIN_NODE) {
-+ s = p;
-+ p = PALIGN(p + strlen(s) + 1, 4);
-+
-+ if (*s == '\0')
-+ s = "/";
-+
-+ Print(L"%*s%a {\n", depth * shift, L" ", s);
-+
-+ depth++;
-+ continue;
-+ }
-+
-+ if (tag == FDT_END_NODE) {
-+ depth--;
-+
-+ Print(L"%*s};\n", depth * shift, L" ");
-+ continue;
-+ }
-+
-+ if (tag == FDT_NOP) {
-+ Print(L"%*s// [NOP]\n", depth * shift, L" ");
-+ continue;
-+ }
-+
-+ if (tag != FDT_PROP) {
-+ Print(L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag);
-+ break;
-+ }
-+ sz = fdt32_to_cpu(GET_CELL(p));
-+ s = p_strings + fdt32_to_cpu(GET_CELL(p));
-+ if (version < 16 && sz >= 8)
-+ p = PALIGN(p, 8);
-+ t = p;
-+
-+ p = PALIGN(p + sz, 4);
-+
-+ Print(L"%*s%a", depth * shift, L" ", s);
-+ PrintData(t, sz);
-+ Print(L";\n");
-+ }
-+}
-+
-+EFI_STATUS
-+EblDumpFdt (
-+ IN UINTN Argc,
-+ IN CHAR8 **Argv
-+ )
-+{
-+ EFI_STATUS Status;
-+ EFI_DEVICE_PATH* FdtDevicePath;
-+ VOID* FdtBlob;
-+ UINTN FdtBlobSize;
-+ UINTN Ret;
-+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
-+
-+ // If no FDT file is passed to the argument then get the one from the platform
-+ if (Argc < 2) {
-+ Status = GetEnvironmentVariable (L"Fdt",NULL,NULL,(VOID**)&FdtDevicePath);
-+ if (Status == EFI_NOT_FOUND) {
-+ // No set yet, get the Default Device Path
-+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
-+ ASSERT_EFI_ERROR(Status);
-+ FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));
-+ }
-+ } else {
-+ return EFI_NOT_FOUND;
-+ }
-+
-+ Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, (EFI_PHYSICAL_ADDRESS*)&FdtBlob, &FdtBlobSize);
-+ if (EFI_ERROR(Status)) {
-+ Print (L"ERROR: Did not find the Fdt Blob.\n");
-+ return Status;
-+ }
-+
-+ Ret = fdt_check_header(FdtBlob);
-+ if (Ret != 0) {
-+ Print (L"ERROR: Device Tree header not valid (err:%d)\n",Ret);
-+ return Status;
-+ }
-+
-+ DumpFdt (FdtBlob);
-+
-+ FreePool (FdtDevicePath);
-+
-+ return EFI_SUCCESS;
-+}
-diff --git a/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
-old mode 100644
-new mode 100755
-index b75dbfb..327a794
---- a/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
-+++ b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.c
-@@ -42,6 +42,12 @@ EblDumpMmu (
- IN UINTN Argc,
- IN CHAR8 **Argv
- );
-+
-+EFI_STATUS
-+EblDumpFdt (
-+ IN UINTN Argc,
-+ IN CHAR8 **Argv
-+ );
-
- /**
- Simple arm disassembler via a library
-@@ -416,6 +422,12 @@ GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
- " list all the Device Paths",
- NULL,
- EblDevicePaths
-+ },
-+ {
-+ "dumpfdt",
-+ " dump the current fdt or the one defined in the arguments",
-+ NULL,
-+ EblDumpFdt
- }
- };
-
-diff --git a/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf
-old mode 100644
-new mode 100755
-index 0eb71a0..9f84c07
---- a/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf
-+++ b/ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf
-@@ -30,12 +30,14 @@
- [Sources.common]
- EblCmdLib.c
- EblCmdMmu.c
-+ EblCmdFdt.c
-
- [Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- ArmPkg/ArmPkg.dec
-+ ArmPlatformPkg/ArmPlatformPkg.dec
-
- [LibraryClasses]
- BaseLib
-@@ -45,6 +47,7 @@
- PerformanceLib
- TimerLib
- BdsLib
-+ FdtLib
-
- [Protocols]
- gEfiDebugSupportProtocolGuid
-@@ -53,3 +56,6 @@
-
- [Guids]
- gEfiDebugImageInfoTableGuid
-+
-+[Pcd]
-+ gArmPlatformTokenSpaceGuid.PcdFdtDevicePath
---
-1.7.0.4
-
diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
new file mode 100644
index 0000000000..aee99bd997
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
@@ -0,0 +1,38 @@
+#/* @file
+# Copyright (c) 2011-2012, ARM Limited. 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FdtLib
+ FILE_GUID = 6b2478c0-be23-11e0-a28c-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FdtLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM
+#
+
+[Sources]
+ fdt_ro.c
+ fdt_rw.c
+ fdt_strerror.c
+ fdt_sw.c
+ fdt_wip.c
+ fdt.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
diff --git a/EmbeddedPkg/Library/FdtLib/Makefile.libfdt b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt
new file mode 100644
index 0000000000..91126c000a
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt
@@ -0,0 +1,10 @@
+# Makefile.libfdt
+#
+# This is not a complete Makefile of itself. Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
+LIBFDT_VERSION = version.lds
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
+LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/EmbeddedPkg/Library/FdtLib/TODO b/EmbeddedPkg/Library/FdtLib/TODO
new file mode 100644
index 0000000000..288437e394
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/TODO
@@ -0,0 +1,3 @@
+- Tree traversal functions
+- Graft function
+- Complete libfdt.h documenting comments
diff --git a/EmbeddedPkg/Library/FdtLib/fdt.c b/EmbeddedPkg/Library/FdtLib/fdt.c
new file mode 100644
index 0000000000..e56833ae9b
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt.c
@@ -0,0 +1,222 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ /* Complete tree */
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ /* Unfinished sequential-write blob */
+ if (fdt_size_dt_struct(fdt) == 0)
+ return -FDT_ERR_BADSTATE;
+ } else {
+ return -FDT_ERR_BADMAGIC;
+ }
+
+ return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
+{
+ const char *p;
+
+ if (fdt_version(fdt) >= 0x11)
+ if (((offset + len) < offset)
+ || ((offset + len) > fdt_size_dt_struct(fdt)))
+ return NULL;
+
+ p = _fdt_offset_ptr(fdt, offset);
+
+ if (p + len < p)
+ return NULL;
+ return p;
+}
+
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
+{
+ const uint32_t *tagp, *lenp;
+ uint32_t tag;
+ int offset = startoffset;
+ const char *p;
+
+ *nextoffset = -FDT_ERR_TRUNCATED;
+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+ if (!tagp)
+ return FDT_END; /* premature end */
+ tag = fdt32_to_cpu(*tagp);
+ offset += FDT_TAGSIZE;
+
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ /* skip name */
+ do {
+ p = fdt_offset_ptr(fdt, offset++, 1);
+ } while (p && (*p != '\0'));
+ if (!p)
+ return FDT_END; /* premature end */
+ break;
+
+ case FDT_PROP:
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ default:
+ return FDT_END;
+ }
+
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+
+ *nextoffset = FDT_TAGALIGN(offset);
+ return tag;
+}
+
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+ int nextoffset = 0;
+ uint32_t tag;
+
+ if (offset >= 0)
+ if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+ return nextoffset;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ case FDT_BEGIN_NODE:
+ if (depth)
+ (*depth)++;
+ break;
+
+ case FDT_END_NODE:
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
+ break;
+
+ case FDT_END:
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
+ }
+ } while (tag != FDT_BEGIN_NODE);
+
+ return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+ int len = strlen(s) + 1;
+ const char *last = strtab + tabsize - len;
+ const char *p;
+
+ for (p = strtab; p <= last; p++)
+ if (memcmp(p, s, len) == 0)
+ return p;
+ return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_totalsize(fdt) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ memmove(buf, fdt, fdt_totalsize(fdt));
+ return 0;
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
new file mode 100644
index 0000000000..f72d13b1d1
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+ int err;
+
+ err = fdt_create(buf, bufsize);
+ if (err)
+ return err;
+
+ err = fdt_finish_reservemap(buf);
+ if (err)
+ return err;
+
+ err = fdt_begin_node(buf, "");
+ if (err)
+ return err;
+
+ err = fdt_end_node(buf);
+ if (err)
+ return err;
+
+ err = fdt_finish(buf);
+ if (err)
+ return err;
+
+ return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_ro.c b/EmbeddedPkg/Library/FdtLib/fdt_ro.c
new file mode 100644
index 0000000000..95fdbeadd4
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_ro.c
@@ -0,0 +1,575 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_nodename_eq(const void *fdt, int offset,
+ const char *s, int len)
+{
+ const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+ if (! p)
+ /* short match */
+ return 0;
+
+ if (memcmp(p, s, len) != 0)
+ return 0;
+
+ if (p[len] == '\0')
+ return 1;
+ else if (!memchr(s, '@', len) && (p[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+ return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+ FDT_CHECK_HEADER(fdt);
+ *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+ *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+ return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+ int i = 0;
+
+ while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+ i++;
+ return i;
+}
+
+static int _nextprop(const void *fdt, int offset)
+{
+ uint32_t tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+ const char *name, int namelen)
+{
+ int depth;
+
+ FDT_CHECK_HEADER(fdt);
+
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
+ return offset;
+
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+ const char *name)
+{
+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ const char *end = path + strlen(path);
+ const char *p = path;
+ int offset = 0;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
+
+ while (*p) {
+ const char *q;
+
+ while (*p == '/')
+ p++;
+ if (! *p)
+ return offset;
+ q = strchr(p, '/');
+ if (! q)
+ q = end;
+
+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+ if (offset < 0)
+ return offset;
+
+ p = q;
+ }
+
+ return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+ const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+ int err;
+
+ if (((err = fdt_check_header(fdt)) != 0)
+ || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ goto fail;
+
+ if (len)
+ *len = strlen(nh->name);
+
+ return nh->name;
+
+ fail:
+ if (len)
+ *len = err;
+ return NULL;
+}
+
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ int err;
+ const struct fdt_property *prop;
+
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
+
+ prop = _fdt_offset_ptr(fdt, offset);
+
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
+
+ return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
+ }
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
+
+ if (lenp)
+ *lenp = offset;
+ return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+ if (! prop)
+ return NULL;
+
+ return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep)
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+ const uint32_t *php;
+ int len;
+
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
+
+ return fdt32_to_cpu(*php);
+}
+
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+ int pdepth = 0, p = 0;
+ int offset, depth, namelen;
+ const char *name;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (buflen < 2)
+ return -FDT_ERR_NOSPACE;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ while (pdepth > depth) {
+ do {
+ p--;
+ } while (buf[p-1] != '/');
+ pdepth--;
+ }
+
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
+ }
+
+ if (offset == nodeoffset) {
+ if (pdepth < (depth + 1))
+ return -FDT_ERR_NOSPACE;
+
+ if (p > 1) /* special case so that root path is "/", not "" */
+ p--;
+ buf[p] = '\0';
+ return 0;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth)
+{
+ int offset, depth;
+ int supernodeoffset = -FDT_ERR_INTERNAL;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (supernodedepth < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth == supernodedepth)
+ supernodeoffset = offset;
+
+ if (offset == nodeoffset) {
+ if (nodedepth)
+ *nodedepth = depth;
+
+ if (supernodedepth > depth)
+ return -FDT_ERR_NOTFOUND;
+ else
+ return supernodeoffset;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+ int nodedepth;
+ int err;
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+ if (err)
+ return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+ if (nodedepth < 0)
+ return nodedepth;
+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ int offset;
+ const void *val;
+ int len;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+ int offset;
+
+ if ((phandle == 0) || (phandle == (uint32_t)-1))
+ return -FDT_ERR_BADPHANDLE;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
+{
+ int len = strlen(str);
+ const char *p;
+
+ while (listlen >= len) {
+ if (memcmp(str, strlist, len+1) == 0)
+ return 1;
+ p = memchr(strlist, '\0', listlen);
+ if (!p)
+ return 0; /* malformed strlist.. */
+ listlen -= (p-strlist) + 1;
+ strlist = p + 1;
+ }
+ return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible)
+{
+ const void *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+ if (!prop)
+ return len;
+ if (_fdt_stringlist_contains(prop, len, compatible))
+ return 0;
+ else
+ return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible)
+{
+ int offset, err;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_node_check_compatible(), then if
+ * that didn't find what we want, we scan over them again
+ * making our way to the next node. Still it's the easiest to
+ * implement approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ err = fdt_node_check_compatible(fdt, offset, compatible);
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+ return err;
+ else if (err == 0)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_rw.c b/EmbeddedPkg/Library/FdtLib/fdt_rw.c
new file mode 100644
index 0000000000..878a775a7b
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_rw.c
@@ -0,0 +1,495 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_blocks_misordered(const void *fdt,
+ int mem_rsv_size, int struct_size)
+{
+ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
+ || (fdt_off_dt_struct(fdt) <
+ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+ || (fdt_off_dt_strings(fdt) <
+ (fdt_off_dt_struct(fdt) + struct_size))
+ || (fdt_totalsize(fdt) <
+ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int _fdt_rw_check_header(void *fdt)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_version(fdt) < 17)
+ return -FDT_ERR_BADVERSION;
+ if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_BADLAYOUT;
+ if (fdt_version(fdt) > 17)
+ fdt_set_version(fdt, 17);
+
+ return 0;
+}
+
+#define FDT_RW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_rw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static inline int _fdt_data_size(void *fdt)
+{
+ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+{
+ char *p = splicepoint;
+ char *end = (char *)fdt + _fdt_data_size(fdt);
+
+ if (((p + oldlen) < p) || ((p + oldlen) > end))
+ return -FDT_ERR_BADOFFSET;
+ if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ return -FDT_ERR_NOSPACE;
+ memmove(p + newlen, p + oldlen, end - p - oldlen);
+ return 0;
+}
+
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+ int oldn, int newn)
+{
+ int delta = (newn - oldn) * sizeof(*p);
+ int err;
+ err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+ if (err)
+ return err;
+ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_struct(void *fdt, void *p,
+ int oldlen, int newlen)
+{
+ int delta = newlen - oldlen;
+ int err;
+
+ err = _fdt_splice(fdt, p, oldlen, newlen);
+ if (err)
+ return err;
+
+ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_string(void *fdt, int newlen)
+{
+ void *p = (char *)fdt
+ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+ int err;
+
+ err = _fdt_splice(fdt, p, 0, newlen);
+ if (err)
+ return err;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+ const char *p;
+ char *new;
+ int len = strlen(s) + 1;
+ int err;
+
+ p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+ if (p)
+ /* found it */
+ return (p - strtab);
+
+ new = strtab + fdt_size_dt_strings(fdt);
+ err = _fdt_splice_string(fdt, len);
+ if (err)
+ return err;
+
+ memcpy(new, s, len);
+ return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
+{
+ struct fdt_reserve_entry *re;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+ err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+ if (err)
+ return err;
+
+ re->address = cpu_to_fdt64(address);
+ re->size = cpu_to_fdt64(size);
+ return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+ struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ if (n >= fdt_num_mem_rsv(fdt))
+ return -FDT_ERR_NOTFOUND;
+
+ err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int oldlen;
+ int err;
+
+ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (! (*prop))
+ return oldlen;
+
+ err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(len));
+ if (err)
+ return err;
+
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int proplen;
+ int nextoffset;
+ int namestroff;
+ int err;
+
+ if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return nextoffset;
+
+ namestroff = _fdt_find_add_string(fdt, name);
+ if (namestroff < 0)
+ return namestroff;
+
+ *prop = _fdt_offset_ptr_w(fdt, nextoffset);
+ proplen = sizeof(**prop) + FDT_TAGALIGN(len);
+
+ err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+ if (err)
+ return err;
+
+ (*prop)->tag = cpu_to_fdt32(FDT_PROP);
+ (*prop)->nameoff = cpu_to_fdt32(namestroff);
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+ char *namep;
+ int oldlen, newlen;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+ if (!namep)
+ return oldlen;
+
+ newlen = strlen(name);
+
+ err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+ FDT_TAGALIGN(newlen+1));
+ if (err)
+ return err;
+
+ memcpy(namep, name, newlen+1);
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+ if (err == -FDT_ERR_NOTFOUND)
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err, oldlen, newlen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (prop) {
+ newlen = len + oldlen;
+ err = _fdt_splice_struct(fdt, prop->data,
+ FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(newlen));
+ if (err)
+ return err;
+ prop->len = cpu_to_fdt32(newlen);
+ memcpy(prop->data + oldlen, val, len);
+ } else {
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+ memcpy(prop->data, val, len);
+ }
+ return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len, proplen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+ return _fdt_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen)
+{
+ struct fdt_node_header *nh;
+ int offset, nextoffset;
+ int nodelen;
+ int err;
+ uint32_t tag;
+ uint32_t *endtag;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+ if (offset >= 0)
+ return -FDT_ERR_EXISTS;
+ else if (offset != -FDT_ERR_NOTFOUND)
+ return offset;
+
+ /* Try to place the new node after the parent's properties */
+ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ } while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+ nh = _fdt_offset_ptr_w(fdt, offset);
+ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
+
+ err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+ if (err)
+ return err;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
+ memcpy(nh->name, name, namelen);
+ endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+ *endtag = cpu_to_fdt32(FDT_END_NODE);
+
+ return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+ endoffset - nodeoffset, 0);
+}
+
+static void _fdt_packblocks(const char *old, char *new,
+ int mem_rsv_size, int struct_size)
+{
+ int mem_rsv_off, struct_off, strings_off;
+
+ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
+ struct_off = mem_rsv_off + mem_rsv_size;
+ strings_off = struct_off + struct_size;
+
+ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+ fdt_set_off_mem_rsvmap(new, mem_rsv_off);
+
+ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+ fdt_set_off_dt_struct(new, struct_off);
+ fdt_set_size_dt_struct(new, struct_size);
+
+ memmove(new + strings_off, old + fdt_off_dt_strings(old),
+ fdt_size_dt_strings(old));
+ fdt_set_off_dt_strings(new, strings_off);
+ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+ int err;
+ int mem_rsv_size, struct_size;
+ int newsize;
+ const char *fdtstart = fdt;
+ const char *fdtend = fdtstart + fdt_totalsize(fdt);
+ char *tmp;
+
+ FDT_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+
+ if (fdt_version(fdt) >= 17) {
+ struct_size = fdt_size_dt_struct(fdt);
+ } else {
+ struct_size = 0;
+ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+ ;
+ if (struct_size < 0)
+ return struct_size;
+ }
+
+ if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+ /* no further work necessary */
+ err = fdt_move(fdt, buf, bufsize);
+ if (err)
+ return err;
+ fdt_set_version(buf, 17);
+ fdt_set_size_dt_struct(buf, struct_size);
+ fdt_set_totalsize(buf, bufsize);
+ return 0;
+ }
+
+ /* Need to reorder */
+ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+ + struct_size + fdt_size_dt_strings(fdt);
+
+ if (bufsize < newsize)
+ return -FDT_ERR_NOSPACE;
+
+ /* First attempt to build converted tree at beginning of buffer */
+ tmp = buf;
+ /* But if that overlaps with the old tree... */
+ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+ /* Try right after the old tree instead */
+ tmp = (char *)(uintptr_t)fdtend;
+ if ((tmp + newsize) > ((char *)buf + bufsize))
+ return -FDT_ERR_NOSPACE;
+ }
+
+ _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+ memmove(buf, tmp, newsize);
+
+ fdt_set_magic(buf, FDT_MAGIC);
+ fdt_set_totalsize(buf, bufsize);
+ fdt_set_version(buf, 17);
+ fdt_set_last_comp_version(buf, 16);
+ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+ return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+ int mem_rsv_size;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+ _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+
+ return 0;
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_strerror.c b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c
new file mode 100644
index 0000000000..e6c3ceee8c
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct fdt_errtabent {
+ const char *str;
+};
+
+#define FDT_ERRTABENT(val) \
+ [(val)] = { .str = #val, }
+
+static struct fdt_errtabent fdt_errtable[] = {
+ FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+ FDT_ERRTABENT(FDT_ERR_EXISTS),
+ FDT_ERRTABENT(FDT_ERR_NOSPACE),
+
+ FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+ FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADSTATE),
+
+ FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+ FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+ FDT_ERRTABENT(FDT_ERR_BADVERSION),
+ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+ FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+ if (errval > 0)
+ return "<valid offset/length>";
+ else if (errval == 0)
+ return "<no error>";
+ else if (errval > -FDT_ERRTABSIZE) {
+ const char *s = fdt_errtable[-errval].str;
+
+ if (s)
+ return s;
+ }
+
+ return "<unknown error>";
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_sw.c b/EmbeddedPkg/Library/FdtLib/fdt_sw.c
new file mode 100644
index 0000000000..55ebebf1eb
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_sw.c
@@ -0,0 +1,256 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_sw_check_header(void *fdt)
+{
+ if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ /* FIXME: should check more details about the header state */
+ return 0;
+}
+
+#define FDT_SW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_sw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static void *_fdt_grab_space(void *fdt, size_t len)
+{
+ int offset = fdt_size_dt_struct(fdt);
+ int spaceleft;
+
+ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+ - fdt_size_dt_strings(fdt);
+
+ if ((offset + len < offset) || (offset + len > spaceleft))
+ return NULL;
+
+ fdt_set_size_dt_struct(fdt, offset + len);
+ return _fdt_offset_ptr_w(fdt, offset);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+ void *fdt = buf;
+
+ if (bufsize < sizeof(struct fdt_header))
+ return -FDT_ERR_NOSPACE;
+
+ memset(buf, 0, bufsize);
+
+ fdt_set_magic(fdt, FDT_SW_MAGIC);
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_totalsize(fdt, bufsize);
+
+ fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+ fdt_set_off_dt_strings(fdt, bufsize);
+
+ return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
+{
+ struct fdt_reserve_entry *re;
+ int offset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ if (fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADSTATE;
+
+ offset = fdt_off_dt_struct(fdt);
+ if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+ return -FDT_ERR_NOSPACE;
+
+ re = (struct fdt_reserve_entry *)((char *)fdt + offset);
+ re->address = cpu_to_fdt64(addr);
+ re->size = cpu_to_fdt64(size);
+
+ fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+ return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+ return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+ struct fdt_node_header *nh;
+ int namelen = strlen(name) + 1;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+ if (! nh)
+ return -FDT_ERR_NOSPACE;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memcpy(nh->name, name, namelen);
+ return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+ uint32_t *en;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+ if (! en)
+ return -FDT_ERR_NOSPACE;
+
+ *en = cpu_to_fdt32(FDT_END_NODE);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ const char *p;
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+ int struct_top, offset;
+
+ p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ /* Add it */
+ offset = -strtabsize - len;
+ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ if (fdt_totalsize(fdt) + offset < struct_top)
+ return 0; /* no more room :( */
+
+ memcpy(strtab + offset, s, len);
+ fdt_set_size_dt_strings(fdt, strtabsize + len);
+ return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+ struct fdt_property *prop;
+ int nameoff;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nameoff = _fdt_find_add_string(fdt, name);
+ if (nameoff == 0)
+ return -FDT_ERR_NOSPACE;
+
+ prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+ if (! prop)
+ return -FDT_ERR_NOSPACE;
+
+ prop->tag = cpu_to_fdt32(FDT_PROP);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ prop->len = cpu_to_fdt32(len);
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+ char *p = (char *)fdt;
+ uint32_t *end;
+ int oldstroffset, newstroffset;
+ uint32_t tag;
+ int offset, nextoffset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ /* Add terminator */
+ end = _fdt_grab_space(fdt, sizeof(*end));
+ if (! end)
+ return -FDT_ERR_NOSPACE;
+ *end = cpu_to_fdt32(FDT_END);
+
+ /* Relocate the string table */
+ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+ fdt_set_off_dt_strings(fdt, newstroffset);
+
+ /* Walk the structure, correcting string offsets */
+ offset = 0;
+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+ if (tag == FDT_PROP) {
+ struct fdt_property *prop =
+ _fdt_offset_ptr_w(fdt, offset);
+ int nameoff;
+
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ nameoff += fdt_size_dt_strings(fdt);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ }
+ offset = nextoffset;
+ }
+ if (nextoffset < 0)
+ return nextoffset;
+
+ /* Finally, adjust the header */
+ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+ fdt_set_magic(fdt, FDT_MAGIC);
+ return 0;
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_wip.c b/EmbeddedPkg/Library/FdtLib/fdt_wip.c
new file mode 100644
index 0000000000..6025fa1fe8
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_wip.c
@@ -0,0 +1,118 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+ if (! propval)
+ return proplen;
+
+ if (proplen != len)
+ return -FDT_ERR_NOSPACE;
+
+ memcpy(propval, val, len);
+ return 0;
+}
+
+static void _fdt_nop_region(void *start, int len)
+{
+ uint32_t *p;
+
+ for (p = start; (char *)p < ((char *)start + len); p++)
+ *p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len;
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ _fdt_nop_region(prop, len + sizeof(*prop));
+
+ return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int offset)
+{
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+ endoffset - nodeoffset);
+ return 0;
+}
diff --git a/EmbeddedPkg/Library/FdtLib/libfdt_internal.h b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h
new file mode 100644
index 0000000000..381133ba81
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h
@@ -0,0 +1,95 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <fdt.h>
+
+#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
+
+#define FDT_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+ return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+ const struct fdt_reserve_entry *rsv_table =
+ (const struct fdt_reserve_entry *)
+ ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
+
+ return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+ return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+}
+
+#define FDT_SW_MAGIC (~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/EmbeddedPkg/Library/FdtLib/version.lds b/EmbeddedPkg/Library/FdtLib/version.lds
new file mode 100644
index 0000000000..3c3994e27f
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/version.lds
@@ -0,0 +1,54 @@
+LIBFDT_1.2 {
+ global:
+ fdt_next_node;
+ fdt_check_header;
+ fdt_move;
+ fdt_string;
+ fdt_num_mem_rsv;
+ fdt_get_mem_rsv;
+ fdt_subnode_offset_namelen;
+ fdt_subnode_offset;
+ fdt_path_offset;
+ fdt_get_name;
+ fdt_get_property_namelen;
+ fdt_get_property;
+ fdt_getprop_namelen;
+ fdt_getprop;
+ fdt_get_phandle;
+ fdt_get_alias_namelen;
+ fdt_get_alias;
+ fdt_get_path;
+ fdt_supernode_atdepth_offset;
+ fdt_node_depth;
+ fdt_parent_offset;
+ fdt_node_offset_by_prop_value;
+ fdt_node_offset_by_phandle;
+ fdt_node_check_compatible;
+ fdt_node_offset_by_compatible;
+ fdt_setprop_inplace;
+ fdt_nop_property;
+ fdt_nop_node;
+ fdt_create;
+ fdt_add_reservemap_entry;
+ fdt_finish_reservemap;
+ fdt_begin_node;
+ fdt_property;
+ fdt_end_node;
+ fdt_finish;
+ fdt_open_into;
+ fdt_pack;
+ fdt_add_mem_rsv;
+ fdt_del_mem_rsv;
+ fdt_set_name;
+ fdt_setprop;
+ fdt_delprop;
+ fdt_add_subnode_namelen;
+ fdt_add_subnode;
+ fdt_del_node;
+ fdt_strerror;
+ fdt_offset_ptr;
+ fdt_next_tag;
+
+ local:
+ *;
+};