--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+* \r
+* This program and the accompanying materials \r
+* are licensed and made available under the terms and conditions of the BSD License \r
+* which accompanies this distribution. The full text of the license may be found at \r
+* http://opensource.org/licenses/bsd-license.php \r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+*\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BdsLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+#include <Protocol/DevicePathFromText.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+\r
+#include <libfdt.h>\r
+\r
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))\r
+#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))\r
+#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))\r
+\r
+STATIC\r
+UINTN\r
+IsPrintableString (\r
+ IN CONST VOID* data,\r
+ IN UINTN len\r
+ )\r
+{\r
+ CONST CHAR8 *s = data;\r
+ CONST CHAR8 *ss;\r
+\r
+ // Zero length is not\r
+ if (len == 0) {\r
+ return 0;\r
+ }\r
+\r
+ // Must terminate with zero\r
+ if (s[len - 1] != '\0') {\r
+ return 0;\r
+ }\r
+\r
+ ss = s;\r
+ while (*s/* && isprint(*s)*/) {\r
+ s++;\r
+ }\r
+\r
+ // Not zero, or not done yet\r
+ if (*s != '\0' || (s + 1 - ss) < len) {\r
+ return 0;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PrintData (\r
+ IN CONST CHAR8* data,\r
+ IN UINTN len\r
+ )\r
+{\r
+ UINTN i;\r
+ CONST CHAR8 *p = data;\r
+\r
+ // No data, don't print\r
+ if (len == 0)\r
+ return;\r
+\r
+ if (IsPrintableString (data, len)) {\r
+ Print(L" = \"%a\"", (const char *)data);\r
+ } else if ((len % 4) == 0) {\r
+ Print(L" = <");\r
+ for (i = 0; i < len; i += 4) {\r
+ Print(L"0x%08x%a", fdt32_to_cpu(GET_CELL(p)),i < (len - 4) ? " " : "");\r
+ }\r
+ Print(L">");\r
+ } else {\r
+ Print(L" = [");\r
+ for (i = 0; i < len; i++)\r
+ Print(L"%02x%a", *p++, i < len - 1 ? " " : "");\r
+ Print(L"]");\r
+ }\r
+}\r
+\r
+VOID\r
+DumpFdt (\r
+ IN VOID* FdtBlob\r
+ )\r
+{\r
+ struct fdt_header *bph;\r
+ UINT32 off_dt;\r
+ UINT32 off_str;\r
+ CONST CHAR8* p_struct;\r
+ CONST CHAR8* p_strings;\r
+ CONST CHAR8* p;\r
+ CONST CHAR8* s;\r
+ CONST CHAR8* t;\r
+ UINT32 tag;\r
+ UINTN sz;\r
+ UINTN depth;\r
+ UINTN shift;\r
+ UINT32 version;\r
+\r
+ depth = 0;\r
+ shift = 4;\r
+\r
+ bph = FdtBlob;\r
+ off_dt = fdt32_to_cpu(bph->off_dt_struct);\r
+ off_str = fdt32_to_cpu(bph->off_dt_strings);\r
+ p_struct = (CONST CHAR8*)FdtBlob + off_dt;\r
+ p_strings = (CONST CHAR8*)FdtBlob + off_str;\r
+ version = fdt32_to_cpu(bph->version);\r
+\r
+ p = p_struct;\r
+ while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {\r
+\r
+ if (tag == FDT_BEGIN_NODE) {\r
+ s = p;\r
+ p = PALIGN(p + strlen(s) + 1, 4);\r
+\r
+ if (*s == '\0')\r
+ s = "/";\r
+\r
+ Print(L"%*s%a {\n", depth * shift, L" ", s);\r
+\r
+ depth++;\r
+ continue;\r
+ }\r
+\r
+ if (tag == FDT_END_NODE) {\r
+ depth--;\r
+\r
+ Print(L"%*s};\n", depth * shift, L" ");\r
+ continue;\r
+ }\r
+\r
+ if (tag == FDT_NOP) {\r
+ Print(L"%*s// [NOP]\n", depth * shift, L" ");\r
+ continue;\r
+ }\r
+\r
+ if (tag != FDT_PROP) {\r
+ Print(L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag);\r
+ break;\r
+ }\r
+ sz = fdt32_to_cpu(GET_CELL(p));\r
+ s = p_strings + fdt32_to_cpu(GET_CELL(p));\r
+ if (version < 16 && sz >= 8)\r
+ p = PALIGN(p, 8);\r
+ t = p;\r
+\r
+ p = PALIGN(p + sz, 4);\r
+\r
+ Print(L"%*s%a", depth * shift, L" ", s);\r
+ PrintData(t, sz);\r
+ Print(L";\n");\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+EblDumpFdt (\r
+ IN UINTN Argc,\r
+ IN CHAR8 **Argv\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH* FdtDevicePath;\r
+ EFI_PHYSICAL_ADDRESS FdtBlob;\r
+ UINTN FdtBlobSize;\r
+ UINTN Ret;\r
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
+\r
+ // If no FDT file is passed to the argument then get the one from the platform\r
+ if (Argc < 2) {\r
+ Status = GetEnvironmentVariable (L"Fdt",NULL,NULL,(VOID**)&FdtDevicePath);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ // No set yet, get the Default Device Path\r
+ Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);\r
+ ASSERT_EFI_ERROR(Status);\r
+ FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath));\r
+ }\r
+ } else {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlob, &FdtBlobSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find the Fdt Blob.\n");\r
+ return Status;\r
+ }\r
+\r
+ Ret = fdt_check_header((CONST VOID*)(UINTN)FdtBlob);\r
+ if (Ret != 0) {\r
+ Print (L"ERROR: Device Tree header not valid (err:%d)\n",Ret);\r
+ return Status;\r
+ }\r
+\r
+ DumpFdt ((VOID*)(UINTN)FdtBlob);\r
+\r
+ FreePool (FdtDevicePath);\r
+\r
+ return EFI_SUCCESS;\r
+}\r