Инструменты Linux для работы с деревом устройств


   dtc        fdtdump        fdtget      fdtput      dtdiff   

Преобразовать dtb в исходный текст
root@orangepizero2:~# fdtdump --help

**** fdtdump is a low-level debugging tool, not meant for general use.
**** If you want to decompile a dtb, you probably want
****     dtc -I dtb -O dts <filename>

**** fdtdump - это инструмент отладки низкого уровня, не предназначенный для общего использования.
**** Если вы хотите декомпилировать dtb, вы, вероятно, используете
**** dtc -I dtb -O dts <имя файла>

Usage: fdtdump [options] <file>

Options: -[dshV]
  -d, --debug   Dump debug information while decoding the file
                дамп отладочной информации при декодировании файла
  -s, --scan    Scan for an embedded fdt in file
                сканировать файл на наличие встроенного fdt
  -h, --help    Print this help and exit
                Вывод этой справки и выход
  -V, --version Print version and exit
                Вывод версии  и выход

Параметры: - [dshV]
  -d, --debug
  -s, --scan


Исходный текст fdtdump.c

Источник: GitHub

/*
 * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <libfdt.h>
#include <libfdt_env.h>
#include <fdt.h>

#include "util.h"

#define ALIGN(x, a)  (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p,a)  ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p)  (p += 4, *((const uint32_t *)(p-4)))

static const char *tagname(uint32_t tag)
{ static const char * const names[] =
   {
#define TN(t) [t] #t
        TN(FDT_BEGIN_NODE),
        TN(FDT_END_NODE),
        TN(FDT_PROP),
        TN(FDT_NOP),
        TN(FDT_END),
#undef TN
  };
   if (tag < ARRAY_SIZE(names))
       if (names[tag])
           return names[tag];
       return "FDT_???";
}

#define dumpf(fmt, args...) \
        do { if (debug) printf("// " fmt, ## args);
        } while (0)

static void dump_blob(void *blob, bool debug)
{
  uintptr_t blob_off = (uintptr_t)blob;
  struct fdt_header *bph = blob;
  uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
  uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
  uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
  struct fdt_reserve_entry *p_rsvmap =
          (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
  const char *p_struct = (const char *)blob + off_dt;
  const char *p_strings = (const char *)blob + off_str;
  uint32_t version = fdt32_to_cpu(bph->version);
  uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
  uint32_t tag;
  const char *p, *s, *t;
  int depth, sz, shift;
  int i;
  uint64_t addr, size;

  depth = 0;
  shift = 4;

  printf("/dts-v1/;\n");
  printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
  printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
  printf("// off_dt_struct:\t0x%x\n", off_dt);
  printf("// off_dt_strings:\t0x%x\n", off_str);
  printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
  printf("// version:\t\t%d\n", version);
  printf("// last_comp_version:\t%d\n",
         fdt32_to_cpu(bph->last_comp_version));
  if (version >= 2)
      printf("// boot_cpuid_phys:\t0x%x\n",
            fdt32_to_cpu(bph->boot_cpuid_phys));

  if (version >= 3)
          printf("// size_dt_strings:\t0x%x\n",
                 fdt32_to_cpu(bph->size_dt_strings));
  if (version >= 17)
          printf("// size_dt_struct:\t0x%x\n",
                 fdt32_to_cpu(bph->size_dt_struct));
  printf("\n");

  for (i = 0; ; i++)
  {
     addr = fdt64_to_cpu(p_rsvmap[i].address);
     size = fdt64_to_cpu(p_rsvmap[i].size);
     if (addr == 0 && size == 0)
             break;

     printf("/memreserve/ %llx %llx;\n",
                 (unsigned long long)addr, (unsigned long long)size);
  }

  p = p_struct;
  while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END)
  {  dumpf("%04zx: tag: 0x%08x (%s)\n",
           (uintptr_t)p - blob_off - 4, tag, tagname(tag));

    if (tag == FDT_BEGIN_NODE)
    {  s = p;
       p = PALIGN(p + strlen(s) + 1, 4);

       if (*s == '\0')
               s = "/";

       printf("%*s%s {\n", depth * shift, "", s);
       depth++;
       continue;
    }

    if (tag == FDT_END_NODE)
    { depth--;
      printf("%*s};\n", depth * shift, "");
      continue;
    }

    if (tag == FDT_NOP)
    { printf("%*s// [NOP]\n", depth * shift, "");
      continue;
    }

    if (tag != FDT_PROP)
    { fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
       break;
    }
    sz = fdt32_to_cpu(GET_CELL(p));
    s = p_strings + fdt32_to_cpu(GET_CELL(p));

    if (version < 16 && sz >= 8)
        p = PALIGN(p, 8);
    t = p;

    p = PALIGN(p + sz, 4);

    dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
    dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
    printf("%*s%s", depth * shift, "", s);
    utilfdt_print_data(t, sz);
    printf(";\n");
  }
}

/* Usage related data. */
static const char usage_synopsis[] = "fdtdump [options] <file>";
static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] =
{
   {"debug",            no_argument, NULL, 'd'},
   {"scan",             no_argument, NULL, 's'},
   USAGE_COMMON_LONG_OPTS
};
static const char * const usage_opts_help[] =
{
  "Dump debug information while decoding the file",
  "Scan for an embedded fdt in file",
  USAGE_COMMON_OPTS_HELP
};

int main(int argc, char *argv[])
{
  int opt;
  const char *file;
  char *buf;
  bool debug = false;
  bool scan = false;
  off_t len;

  while ((opt = util_getopt_long()) != EOF)
  { switch (opt)
     { case_USAGE_COMMON_FLAGS
       case 'd':
              debug = true;
              break;
       case 's':
              scan = true;
              break;
     }
  }
  if (optind != argc - 1)
          usage("missing input filename");
  file = argv[optind];

  buf = utilfdt_read_len(file, &len);
  if (!buf)
          die("could not read: %s\n", file);

  /* try and locate an embedded fdt in a bigger blob */
  if (scan)
  { unsigned char smagic[4];
    char *p = buf;
    char *endp = buf + len;

    fdt_set_magic(smagic, FDT_MAGIC);

    /* poor man's memmem */
    while (true)
    { p = memchr(p, smagic[0], endp - p - 4);
      if (!p)
         break;
      if (fdt_magic(p) == FDT_MAGIC)
       { /* try and validate the main struct */
          off_t this_len = endp - p;
          fdt32_t max_version = 17;
          if (fdt_version(p) <= max_version &&
              fdt_last_comp_version(p) < max_version &&
              fdt_totalsize(p) < this_len &&
              fdt_off_dt_struct(p) < this_len &&
                  fdt_off_dt_strings(p) < this_len)
                  break;
          if (debug)
             printf("%s: skipping fdt magic at offset %#zx\n",
                    file, p - buf);
       }
       ++p;
    }
    if (!p)
      die("%s: could not locate fdt magic\n", file);
    printf("%s: found fdt at offset %#zx\n", file, p - buf);
    buf = p;
  }

  dump_blob(buf, debug);

  return 0;
}