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