From 48837c22861339eb46af60131b72d9f89aa228c1 Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Fri, 24 Feb 2012 15:47:29 +0000 Subject: [PATCH] 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 --- .../0001-EmbeddedPkg-Added-libfdt-port.patch | 220 ++++++++ ...ded-support-for-modifying-the-passed.patch | 489 ++++++++++++++++++ ...kg-EblCmdLib-Add-dumpfdt-EBL-command.patch | 300 +++++++++++ EmbeddedPkg/Library/FdtLib/README.txt | 1 + 4 files changed, 1010 insertions(+) create mode 100644 EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch create mode 100644 EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch create mode 100644 EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch create mode 100755 EmbeddedPkg/Library/FdtLib/README.txt diff --git a/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch b/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch new file mode 100644 index 0000000000..ae06b6f396 --- /dev/null +++ b/EmbeddedPkg/Library/FdtLib/0001-EmbeddedPkg-Added-libfdt-port.patch @@ -0,0 +1,220 @@ +From 669778eab2092ef85ed5b5e537203721cfb1215d Mon Sep 17 00:00:00 2001 +From: Olivier Martin +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 ++#include ++ ++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 ++Date: Mon Dec 5 12:22:07 2011 +1100 ++ ++# Latest commit in libfdt : ++commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86 ++Author: Minghuan Lian ++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 new file mode 100644 index 0000000000..66ea902875 --- /dev/null +++ b/EmbeddedPkg/Library/FdtLib/0002-ArmPkg-BdsLib-Added-support-for-modifying-the-passed.patch @@ -0,0 +1,489 @@ +From 9c16a23fba659cdf0ce798aa085a4fb8c3bd47d1 Mon Sep 17 00:00:00 2001 +From: Olivier Martin +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 ++#include ++ ++#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 ++ + #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 new file mode 100644 index 0000000000..98fc8fcb13 --- /dev/null +++ b/EmbeddedPkg/Library/FdtLib/0003-ArmPlatformPkg-EblCmdLib-Add-dumpfdt-EBL-command.patch @@ -0,0 +1,300 @@ +From 82540f3a4b280133f2d1a58cb8baba01c1f09690 Mon Sep 17 00:00:00 2001 +From: Olivier Martin +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#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/README.txt b/EmbeddedPkg/Library/FdtLib/README.txt new file mode 100755 index 0000000000..fb4010539f --- /dev/null +++ b/EmbeddedPkg/Library/FdtLib/README.txt @@ -0,0 +1 @@ +See: https://sourceforge.net/apps/mediawiki/tianocore/index.php?title=EmbeddedPkg/Fdt \ No newline at end of file -- 2.39.2