Home | History | Annotate | Download | only in FdtPlatformDxe
      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 
     21 STATIC
     22 UINTN
     23 IsPrintableString (
     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 
     54 STATIC
     55 VOID
     56 PrintData (
     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 
     84 STATIC
     85 VOID
     86 DumpFdt (
     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 **/
    193 SHELL_STATUS
    194 EFIAPI
    195 ShellDynCmdDumpFdtHandler (
    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 **/
    264 CHAR16*
    265 EFIAPI
    266 ShellDynCmdDumpFdtGetHelp (
    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