EmbeddedPkg/FdtLib: Added patches to support libfdt in EDK2

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13029 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin 2012-02-24 15:47:29 +00:00
parent be759f774f
commit 48837c2286
4 changed files with 1010 additions and 0 deletions

View File

@ -0,0 +1,220 @@
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

View File

@ -0,0 +1,489 @@
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

View File

@ -0,0 +1,300 @@
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

View File

@ -0,0 +1 @@
See: https://sourceforge.net/apps/mediawiki/tianocore/index.php?title=EmbeddedPkg/Fdt