1/** @file 2 3 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR> 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 "FdtPlatform.h" 16 17#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 18#define PALIGN(p, a) ((void *)(ALIGN ((unsigned long)(p), (a)))) 19#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) 20 21STATIC 22UINTN 23IsPrintableString ( 24 IN CONST VOID* data, 25 IN UINTN len 26 ) 27{ 28 CONST CHAR8 *s = data; 29 CONST CHAR8 *ss; 30 31 // Zero length is not 32 if (len == 0) { 33 return 0; 34 } 35 36 // Must terminate with zero 37 if (s[len - 1] != '\0') { 38 return 0; 39 } 40 41 ss = s; 42 while (*s/* && isprint (*s)*/) { 43 s++; 44 } 45 46 // Not zero, or not done yet 47 if (*s != '\0' || (s + 1 - ss) < len) { 48 return 0; 49 } 50 51 return 1; 52} 53 54STATIC 55VOID 56PrintData ( 57 IN CONST CHAR8* data, 58 IN UINTN len 59 ) 60{ 61 UINTN i; 62 CONST CHAR8 *p = data; 63 64 // No data, don't print 65 if (len == 0) 66 return; 67 68 if (IsPrintableString (data, len)) { 69 Print (L" = \"%a\"", (const char *)data); 70 } else if ((len % 4) == 0) { 71 Print (L" = <"); 72 for (i = 0; i < len; i += 4) { 73 Print (L"0x%08x%a", fdt32_to_cpu (GET_CELL (p)), i < (len - 4) ? " " : ""); 74 } 75 Print (L">"); 76 } else { 77 Print (L" = ["); 78 for (i = 0; i < len; i++) 79 Print (L"%02x%a", *p++, i < len - 1 ? " " : ""); 80 Print (L"]"); 81 } 82} 83 84STATIC 85VOID 86DumpFdt ( 87 IN VOID* FdtBlob 88 ) 89{ 90 struct fdt_header *bph; 91 UINT32 off_dt; 92 UINT32 off_str; 93 CONST CHAR8* p_struct; 94 CONST CHAR8* p_strings; 95 CONST CHAR8* p; 96 CONST CHAR8* s; 97 CONST CHAR8* t; 98 UINT32 tag; 99 UINTN sz; 100 UINTN depth; 101 UINTN shift; 102 UINT32 version; 103 104 { 105 // Can 'memreserve' be printed by below code? 106 INTN num = fdt_num_mem_rsv (FdtBlob); 107 INTN i, err; 108 UINT64 addr = 0, size = 0; 109 110 for (i = 0; i < num; i++) { 111 err = fdt_get_mem_rsv (FdtBlob, i, &addr, &size); 112 if (err) { 113 DEBUG ((EFI_D_ERROR, "Error (%d) : Cannot get memreserve section (%d)\n", err, i)); 114 } 115 else { 116 Print (L"/memreserve/ \t0x%lx \t0x%lx;\n", addr, size); 117 } 118 } 119 } 120 121 depth = 0; 122 shift = 4; 123 124 bph = FdtBlob; 125 off_dt = fdt32_to_cpu (bph->off_dt_struct); 126 off_str = fdt32_to_cpu (bph->off_dt_strings); 127 p_struct = (CONST CHAR8*)FdtBlob + off_dt; 128 p_strings = (CONST CHAR8*)FdtBlob + off_str; 129 version = fdt32_to_cpu (bph->version); 130 131 p = p_struct; 132 while ((tag = fdt32_to_cpu (GET_CELL (p))) != FDT_END) { 133 if (tag == FDT_BEGIN_NODE) { 134 s = p; 135 p = PALIGN (p + AsciiStrLen (s) + 1, 4); 136 137 if (*s == '\0') 138 s = "/"; 139 140 Print (L"%*s%a {\n", depth * shift, L" ", s); 141 142 depth++; 143 continue; 144 } 145 146 if (tag == FDT_END_NODE) { 147 depth--; 148 149 Print (L"%*s};\n", depth * shift, L" "); 150 continue; 151 } 152 153 if (tag == FDT_NOP) { 154 Print (L"%*s// [NOP]\n", depth * shift, L" "); 155 continue; 156 } 157 158 if (tag != FDT_PROP) { 159 Print (L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag); 160 break; 161 } 162 sz = fdt32_to_cpu (GET_CELL (p)); 163 s = p_strings + fdt32_to_cpu (GET_CELL (p)); 164 if (version < 16 && sz >= 8) 165 p = PALIGN (p, 8); 166 t = p; 167 168 p = PALIGN (p + sz, 4); 169 170 Print (L"%*s%a", depth * shift, L" ", s); 171 PrintData (t, sz); 172 Print (L";\n"); 173 } 174} 175 176/** 177 This is the shell command "dumpfdt" handler function. This function handles 178 the command when it is invoked in the shell. 179 180 @param[in] This The instance of the 181 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. 182 @param[in] SystemTable The pointer to the UEFI system table. 183 @param[in] ShellParameters The parameters associated with the command. 184 @param[in] Shell The instance of the shell protocol used in the 185 context of processing this command. 186 187 @return SHELL_SUCCESS The operation was successful. 188 @return SHELL_ABORTED Operation aborted due to internal error. 189 @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table 190 @return SHELL_OUT_OF_RESOURCES A memory allocation failed. 191 192**/ 193SHELL_STATUS 194EFIAPI 195ShellDynCmdDumpFdtHandler ( 196 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, 197 IN EFI_SYSTEM_TABLE *SystemTable, 198 IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, 199 IN EFI_SHELL_PROTOCOL *Shell 200 ) 201{ 202 SHELL_STATUS ShellStatus; 203 EFI_STATUS Status; 204 VOID *FdtBlob; 205 206 ShellStatus = SHELL_SUCCESS; 207 208 // 209 // Install the Shell and Shell Parameters Protocols on the driver 210 // image. This is necessary for the initialisation of the Shell 211 // Library to succeed in the next step. 212 // 213 Status = gBS->InstallMultipleProtocolInterfaces ( 214 &gImageHandle, 215 &gEfiShellProtocolGuid, Shell, 216 &gEfiShellParametersProtocolGuid, ShellParameters, 217 NULL 218 ); 219 if (EFI_ERROR (Status)) { 220 return SHELL_ABORTED; 221 } 222 223 // 224 // Initialise the Shell Library as we are going to use it. 225 // Assert that the return code is EFI_SUCCESS as it should. 226 // To anticipate any change is the codes returned by 227 // ShellInitialize(), leave in case of error. 228 // 229 Status = ShellInitialize (); 230 if (EFI_ERROR (Status)) { 231 ASSERT_EFI_ERROR (Status); 232 return SHELL_ABORTED; 233 } 234 235 Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob); 236 if (EFI_ERROR (Status)) { 237 Print (L"ERROR: Did not find the Fdt Blob.\n"); 238 return EfiCodeToShellCode (Status); 239 } 240 241 DumpFdt (FdtBlob); 242 243 gBS->UninstallMultipleProtocolInterfaces ( 244 gImageHandle, 245 &gEfiShellProtocolGuid, Shell, 246 &gEfiShellParametersProtocolGuid, ShellParameters, 247 NULL 248 ); 249 250 return ShellStatus; 251} 252 253/** 254 This is the shell command "dumpfdt" help handler function. This 255 function returns the formatted help for the "dumpfdt" command. 256 The format matchs that in Appendix B of the revision 2.1 of the 257 UEFI Shell Specification. 258 259 @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. 260 @param[in] Language The pointer to the language string to use. 261 262 @return CHAR16* Pool allocated help string, must be freed by caller. 263**/ 264CHAR16* 265EFIAPI 266ShellDynCmdDumpFdtGetHelp ( 267 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, 268 IN CONST CHAR8 *Language 269 ) 270{ 271 // 272 // This allocates memory. The caller has to free the allocated memory. 273 // 274 return HiiGetString ( 275 mFdtPlatformDxeHiiHandle, 276 STRING_TOKEN (STR_GET_HELP_DUMPFDT), 277 Language 278 ); 279} 280