\r
#include <Protocol/DevicePath.h>\r
\r
-#include <libfdt.h>\r
-\r
//\r
// Internal variables\r
//\r
ShellDynCmdSetFdtGetHelp // GetHelp\r
};\r
\r
+STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolDumpFdt = {\r
+ L"dumpfdt", // Name of the command\r
+ ShellDynCmdDumpFdtHandler, // Handler\r
+ ShellDynCmdDumpFdtGetHelp // GetHelp\r
+};\r
+\r
STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid = {\r
0x8afa7610, 0x62b1, 0x46aa,\r
{0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
\r
//\r
// Install the Device Tree from its expected location\r
return Status;\r
}\r
\r
- //\r
- // If the development features are enabled, install the dynamic shell\r
- // command "setfdt" to be able to define a device path for the FDT\r
- // that has precedence over the device paths defined by\r
- // "PcdFdtDevicePaths".\r
- //\r
-\r
- if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
+ if (FeaturePcdGet (PcdOverridePlatformFdt) || FeaturePcdGet (PcdDumpFdtShellCommand)) {\r
//\r
// Register the strings for the user interface in the HII Database.\r
// This shows the way to the multi-language support, even if\r
FdtPlatformDxeStrings,\r
NULL\r
);\r
+ }\r
+\r
+ //\r
+ // If the development features are enabled, install the dynamic shell\r
+ // command "setfdt" to be able to define a device path for the FDT\r
+ // that has precedence over the device paths defined by\r
+ // "PcdFdtDevicePaths".\r
+ //\r
\r
+ if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
if (mFdtPlatformDxeHiiHandle != NULL) {\r
+ // We install dynamic EFI command on separate handles as we cannot register\r
+ // more than one protocol of the same protocol interface on the same handle.\r
+ Handle = NULL;\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ImageHandle,\r
+ &Handle,\r
&gEfiShellDynamicCommandProtocolGuid,\r
&mShellDynCmdProtocolSetFdt,\r
NULL\r
}\r
}\r
\r
+ if (FeaturePcdGet (PcdDumpFdtShellCommand)) {\r
+ if (mFdtPlatformDxeHiiHandle != NULL) {\r
+ // We install dynamic EFI command on separate handles as we cannot register\r
+ // more than one protocol of the same protocol interface on the same handle.\r
+ Handle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiShellDynamicCommandProtocolGuid,\r
+ &mShellDynCmdProtocolDumpFdt,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ HiiRemovePackages (mFdtPlatformDxeHiiHandle);\r
+ }\r
+ } else {\r
+ Status = EFI_LOAD_ERROR;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_WARN,\r
+ "Unable to install \"dumpfdt\" EFI Shell command - %r \n",\r
+ Status\r
+ ));\r
+ }\r
+ }\r
+\r
return Status;\r
}\r
\r
IN CONST CHAR8 *Language\r
);\r
\r
+/**\r
+ This is the shell command "dumpfdt" handler function. This function handles\r
+ the command when it is invoked in the shell.\r
+\r
+ @param[in] This The instance of the\r
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] SystemTable The pointer to the UEFI system table.\r
+ @param[in] ShellParameters The parameters associated with the command.\r
+ @param[in] Shell The instance of the shell protocol used in the\r
+ context of processing this command.\r
+\r
+ @return SHELL_SUCCESS The operation was successful.\r
+ @return SHELL_ABORTED Operation aborted due to internal error.\r
+ @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table\r
+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellDynCmdDumpFdtHandler (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN EFI_SYSTEM_TABLE *SystemTable,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
+ IN EFI_SHELL_PROTOCOL *Shell\r
+ );\r
+\r
+/**\r
+ This is the shell command "dumpfdt" help handler function. This\r
+ function returns the formatted help for the "dumpfdt" command.\r
+ The format matchs that in Appendix B of the revision 2.1 of the\r
+ UEFI Shell Specification.\r
+\r
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] Language The pointer to the language string to use.\r
+\r
+ @return CHAR16* Pool allocated help string, must be freed by caller.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellDynCmdDumpFdtGetHelp (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN CONST CHAR8 *Language\r
+ );\r
+\r
#endif /* __FDT_PLATFORM_DXE_H__ */\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\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 "FdtPlatform.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
+STATIC\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
+ {\r
+ // Can 'memreserve' be printed by below code?\r
+ INTN num = fdt_num_mem_rsv (FdtBlob);\r
+ INTN i, err;\r
+ UINT64 addr = 0, size = 0;\r
+\r
+ for (i = 0; i < num; i++) {\r
+ err = fdt_get_mem_rsv (FdtBlob, i, &addr, &size);\r
+ if (err) {\r
+ DEBUG ((EFI_D_ERROR, "Error (%d) : Cannot get memreserve section (%d)\n", err, i));\r
+ }\r
+ else {\r
+ Print (L"/memreserve/ \t0x%lx \t0x%lx;\n", addr, size);\r
+ }\r
+ }\r
+ }\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
+ if (tag == FDT_BEGIN_NODE) {\r
+ s = p;\r
+ p = PALIGN (p + AsciiStrLen (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
+/**\r
+ This is the shell command "dumpfdt" handler function. This function handles\r
+ the command when it is invoked in the shell.\r
+\r
+ @param[in] This The instance of the\r
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] SystemTable The pointer to the UEFI system table.\r
+ @param[in] ShellParameters The parameters associated with the command.\r
+ @param[in] Shell The instance of the shell protocol used in the\r
+ context of processing this command.\r
+\r
+ @return SHELL_SUCCESS The operation was successful.\r
+ @return SHELL_ABORTED Operation aborted due to internal error.\r
+ @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table\r
+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
+\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellDynCmdDumpFdtHandler (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN EFI_SYSTEM_TABLE *SystemTable,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
+ IN EFI_SHELL_PROTOCOL *Shell\r
+ )\r
+{\r
+ SHELL_STATUS ShellStatus;\r
+ EFI_STATUS Status;\r
+ VOID *FdtBlob;\r
+\r
+ ShellStatus = SHELL_SUCCESS;\r
+\r
+ //\r
+ // Install the Shell and Shell Parameters Protocols on the driver\r
+ // image. This is necessary for the initialisation of the Shell\r
+ // Library to succeed in the next step.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &gImageHandle,\r
+ &gEfiShellProtocolGuid, Shell,\r
+ &gEfiShellParametersProtocolGuid, ShellParameters,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return SHELL_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Initialise the Shell Library as we are going to use it.\r
+ // Assert that the return code is EFI_SUCCESS as it should.\r
+ // To anticipate any change is the codes returned by\r
+ // ShellInitialize(), leave in case of error.\r
+ //\r
+ Status = ShellInitialize ();\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return SHELL_ABORTED;\r
+ }\r
+\r
+ Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob);\r
+ if (EFI_ERROR (Status)) {\r
+ Print (L"ERROR: Did not find the Fdt Blob.\n");\r
+ return EfiCodeToShellCode (Status);\r
+ }\r
+\r
+ DumpFdt (FdtBlob);\r
+\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ gImageHandle,\r
+ &gEfiShellProtocolGuid, Shell,\r
+ &gEfiShellParametersProtocolGuid, ShellParameters,\r
+ NULL\r
+ );\r
+\r
+ return ShellStatus;\r
+}\r
+\r
+/**\r
+ This is the shell command "dumpfdt" help handler function. This\r
+ function returns the formatted help for the "dumpfdt" command.\r
+ The format matchs that in Appendix B of the revision 2.1 of the\r
+ UEFI Shell Specification.\r
+\r
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] Language The pointer to the language string to use.\r
+\r
+ @return CHAR16* Pool allocated help string, must be freed by caller.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellDynCmdDumpFdtGetHelp (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN CONST CHAR8 *Language\r
+ )\r
+{\r
+ //\r
+ // This allocates memory. The caller has to free the allocated memory.\r
+ //\r
+ return HiiGetString (\r
+ mFdtPlatformDxeHiiHandle,\r
+ STRING_TOKEN (STR_GET_HELP_DUMPFDT),\r
+ Language\r
+ );\r
+}\r