1 /** @file 2 * 3 * Copyright (c) 2011-2013, ARM Limited. All rights reserved. 4 * 5 * This program and the accompanying materials 6 * are licensed and made available under the terms and conditions of the BSD License 7 * which accompanies this distribution. The full text of the license may be found at 8 * http://opensource.org/licenses/bsd-license.php 9 * 10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 * 13 **/ 14 15 #include <Base.h> 16 #include <Uefi.h> 17 #include <Library/MemoryAllocationLib.h> 18 #include <Library/BdsLib.h> 19 #include <Library/DebugLib.h> 20 #include <Library/PcdLib.h> 21 #include <Library/PrintLib.h> 22 #include <Library/UefiLib.h> 23 #include <Library/UefiApplicationEntryPoint.h> 24 #include <Library/UefiBootServicesTableLib.h> 25 #include <Library/UefiRuntimeServicesTableLib.h> 26 27 #include <Protocol/DevicePathFromText.h> 28 29 #include <Guid/Fdt.h> 30 31 #include <libfdt.h> 32 33 #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 34 #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) 35 #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) 36 37 STATIC 38 UINTN 39 IsPrintableString ( 40 IN CONST VOID* data, 41 IN UINTN len 42 ) 43 { 44 CONST CHAR8 *s = data; 45 CONST CHAR8 *ss; 46 47 // Zero length is not 48 if (len == 0) { 49 return 0; 50 } 51 52 // Must terminate with zero 53 if (s[len - 1] != '\0') { 54 return 0; 55 } 56 57 ss = s; 58 while (*s/* && isprint(*s)*/) { 59 s++; 60 } 61 62 // Not zero, or not done yet 63 if (*s != '\0' || (s + 1 - ss) < len) { 64 return 0; 65 } 66 67 return 1; 68 } 69 70 STATIC 71 VOID 72 PrintData ( 73 IN CONST CHAR8* data, 74 IN UINTN len 75 ) 76 { 77 UINTN i; 78 CONST CHAR8 *p = data; 79 80 // No data, don't print 81 if (len == 0) 82 return; 83 84 if (IsPrintableString (data, len)) { 85 Print(L" = \"%a\"", (const char *)data); 86 } else if ((len % 4) == 0) { 87 Print(L" = <"); 88 for (i = 0; i < len; i += 4) { 89 Print(L"0x%08x%a", fdt32_to_cpu(GET_CELL(p)),i < (len - 4) ? " " : ""); 90 } 91 Print(L">"); 92 } else { 93 Print(L" = ["); 94 for (i = 0; i < len; i++) 95 Print(L"%02x%a", *p++, i < len - 1 ? " " : ""); 96 Print(L"]"); 97 } 98 } 99 100 VOID 101 DumpFdt ( 102 IN VOID* FdtBlob 103 ) 104 { 105 struct fdt_header *bph; 106 UINT32 off_dt; 107 UINT32 off_str; 108 CONST CHAR8* p_struct; 109 CONST CHAR8* p_strings; 110 CONST CHAR8* p; 111 CONST CHAR8* s; 112 CONST CHAR8* t; 113 UINT32 tag; 114 UINTN sz; 115 UINTN depth; 116 UINTN shift; 117 UINT32 version; 118 119 depth = 0; 120 shift = 4; 121 122 bph = FdtBlob; 123 off_dt = fdt32_to_cpu(bph->off_dt_struct); 124 off_str = fdt32_to_cpu(bph->off_dt_strings); 125 p_struct = (CONST CHAR8*)FdtBlob + off_dt; 126 p_strings = (CONST CHAR8*)FdtBlob + off_str; 127 version = fdt32_to_cpu(bph->version); 128 129 p = p_struct; 130 while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { 131 132 if (tag == FDT_BEGIN_NODE) { 133 s = p; 134 p = PALIGN(p + strlen(s) + 1, 4); 135 136 if (*s == '\0') 137 s = "/"; 138 139 Print(L"%*s%a {\n", depth * shift, L" ", s); 140 141 depth++; 142 continue; 143 } 144 145 if (tag == FDT_END_NODE) { 146 depth--; 147 148 Print(L"%*s};\n", depth * shift, L" "); 149 continue; 150 } 151 152 if (tag == FDT_NOP) { 153 Print(L"%*s// [NOP]\n", depth * shift, L" "); 154 continue; 155 } 156 157 if (tag != FDT_PROP) { 158 Print(L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag); 159 break; 160 } 161 sz = fdt32_to_cpu(GET_CELL(p)); 162 s = p_strings + fdt32_to_cpu(GET_CELL(p)); 163 if (version < 16 && sz >= 8) 164 p = PALIGN(p, 8); 165 t = p; 166 167 p = PALIGN(p + sz, 4); 168 169 Print(L"%*s%a", depth * shift, L" ", s); 170 PrintData(t, sz); 171 Print(L";\n"); 172 } 173 } 174 175 EFI_STATUS 176 EblDumpFdt ( 177 IN UINTN Argc, 178 IN CHAR8 **Argv 179 ) 180 { 181 EFI_STATUS Status; 182 VOID *FdtBlob; 183 UINTN Ret; 184 185 // If no FDT file is passed to the argument then get the one from the platform 186 if (Argc < 2) { 187 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob); 188 if (EFI_ERROR (Status)) { 189 Print (L"ERROR: Did not find the Fdt Blob.\n"); 190 return Status; 191 } 192 } else { 193 return EFI_NOT_FOUND; 194 } 195 196 Ret = fdt_check_header (FdtBlob); 197 if (Ret != 0) { 198 Print (L"ERROR: Device Tree header not valid (err:%d)\n", Ret); 199 return EFI_INVALID_PARAMETER; 200 } 201 202 DumpFdt (FdtBlob); 203 204 return EFI_SUCCESS; 205 } 206