Home | History | Annotate | Download | only in EblCmdLib
      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