text: /*
   * Copyright (c) 2014 Brian Swetland
   *
   * Use of this source code is governed by a MIT-style
   * license that can be found in the LICENSE file or at
   * https://opensource.org/licenses/MIT
   */
  
  #include "devicetree.h"
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <fcntl.h>
  #include <errno.h>
  
  void error(const char *msg) {
      printf("error: %s\n", msg);
  };
  
  void indent(u32 n) {
      while (n-- > 0)
          putchar(' ');
  }
  
  void hexdump(u8 *data, u32 count) {
      while (count-- > 0)
          printf("%02x ", *data++);
  }
  
  int loadfile(const char *fn, dt_slice_t *out) {
      void *data = NULL;
      off_t end;
      int fd;
      if ((fd = open(fn, O_RDONLY)) < 0)
          return -1;
      if ((end = lseek(fd, 0, SEEK_END)) == -1)
          goto oops;
      if (lseek(fd, 0, SEEK_SET))
          goto oops;
      if ((data = malloc(end + 1)) == NULL)
          goto oops;
      if ((read(fd, data, end) != end))
          goto oops;
      out->data = data;
      out->size = end;
      close(fd);
      return 0;
  oops:
      free(data);
      close(fd);
      return -1;
  }
  
  static int _depth = 0;
  
  int node_cb(int depth, const char *name, void *cookie) {
      _depth = depth;
      indent(depth*2);
      printf("node: '%s'\n", name);
      return 0;
  }
  
  int prop_cb(const char *name, u8 *data, u32 size, void *cookie) {
      indent(_depth * 2 + 2);
      printf("prop '%s' sz=%d\n", name, size);
      indent(_depth * 2 + 2);
      printf("data ");
      hexdump(data, size);
      printf("\n");
      return 0;
  }
  
  int main(int argc, char **argv) {
      devicetree_t dt;
      dt_slice_t s;
  
      dt.error = error;
  
      if (argc != 2)
          return -1;
      if (loadfile(argv[1], &s))
          return -1;
      if (dt_init(&dt, s.data, s.size))
          return -1;
  
      printf("magic %x\n", dt.hdr.magic);
      printf("size %d\n", dt.hdr.size);
      printf("off_struct %d (%d)\n", dt.hdr.off_struct, dt.hdr.sz_struct);
      printf("off_strings %d (%d)\n", dt.hdr.off_strings, dt.hdr.sz_strings);
      printf("version %d (min %d)\n", dt.hdr.version, dt.hdr.version_compat);
  
      dt_walk(&dt, node_cb, prop_cb, NULL);
      return 0;
  }
  
  