1// SPDX-License-Identifier: GPL-2.0 2/* 3 * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com> 4 */ 5 6#include <stdint.h> 7#include <stdio.h> 8#include <stdlib.h> 9#include <string.h> 10#include <ctype.h> 11 12#include <fdt.h> 13#include <libfdt_env.h> 14 15#include "util.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 21static void print_data(const char *data, int len) 22{ 23 int i; 24 const char *p = data; 25 26 /* no data, don't print */ 27 if (len == 0) 28 return; 29 30 if (util_is_printable_string(data, len)) { 31 printf(" = \"%s\"", (const char *)data); 32 } else if ((len % 4) == 0) { 33 printf(" = <"); 34 for (i = 0; i < len; i += 4) 35 printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), 36 i < (len - 4) ? " " : ""); 37 printf(">"); 38 } else { 39 printf(" = ["); 40 for (i = 0; i < len; i++) 41 printf("%02x%s", *p++, i < len - 1 ? " " : ""); 42 printf("]"); 43 } 44} 45 46static void dump_blob(void *blob) 47{ 48 struct fdt_header *bph = blob; 49 uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); 50 uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); 51 uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); 52 struct fdt_reserve_entry *p_rsvmap = 53 (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); 54 const char *p_struct = (const char *)blob + off_dt; 55 const char *p_strings = (const char *)blob + off_str; 56 uint32_t version = fdt32_to_cpu(bph->version); 57 uint32_t totalsize = fdt32_to_cpu(bph->totalsize); 58 uint32_t tag; 59 const char *p, *s, *t; 60 int depth, sz, shift; 61 int i; 62 uint64_t addr, size; 63 64 depth = 0; 65 shift = 4; 66 67 printf("/dts-v1/;\n"); 68 printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); 69 printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); 70 printf("// off_dt_struct:\t0x%x\n", off_dt); 71 printf("// off_dt_strings:\t0x%x\n", off_str); 72 printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); 73 printf("// version:\t\t%d\n", version); 74 printf("// last_comp_version:\t%d\n", 75 fdt32_to_cpu(bph->last_comp_version)); 76 if (version >= 2) 77 printf("// boot_cpuid_phys:\t0x%x\n", 78 fdt32_to_cpu(bph->boot_cpuid_phys)); 79 80 if (version >= 3) 81 printf("// size_dt_strings:\t0x%x\n", 82 fdt32_to_cpu(bph->size_dt_strings)); 83 if (version >= 17) 84 printf("// size_dt_struct:\t0x%x\n", 85 fdt32_to_cpu(bph->size_dt_struct)); 86 printf("\n"); 87 88 for (i = 0; ; i++) { 89 addr = fdt64_to_cpu(p_rsvmap[i].address); 90 size = fdt64_to_cpu(p_rsvmap[i].size); 91 if (addr == 0 && size == 0) 92 break; 93 94 printf("/memreserve/ %llx %llx;\n", 95 (unsigned long long)addr, (unsigned long long)size); 96 } 97 98 p = p_struct; 99 while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { 100 101 /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ 102 103 if (tag == FDT_BEGIN_NODE) { 104 s = p; 105 p = PALIGN(p + strlen(s) + 1, 4); 106 107 if (*s == '\0') 108 s = "/"; 109 110 printf("%*s%s {\n", depth * shift, "", s); 111 112 depth++; 113 continue; 114 } 115 116 if (tag == FDT_END_NODE) { 117 depth--; 118 119 printf("%*s};\n", depth * shift, ""); 120 continue; 121 } 122 123 if (tag == FDT_NOP) { 124 printf("%*s// [NOP]\n", depth * shift, ""); 125 continue; 126 } 127 128 if (tag != FDT_PROP) { 129 fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); 130 break; 131 } 132 sz = fdt32_to_cpu(GET_CELL(p)); 133 s = p_strings + fdt32_to_cpu(GET_CELL(p)); 134 if (version < 16 && sz >= 8) 135 p = PALIGN(p, 8); 136 t = p; 137 138 p = PALIGN(p + sz, 4); 139 140 printf("%*s%s", depth * shift, "", s); 141 print_data(t, sz); 142 printf(";\n"); 143 } 144} 145 146 147int main(int argc, char *argv[]) 148{ 149 char *buf; 150 151 if (argc < 2) { 152 fprintf(stderr, "supply input filename\n"); 153 return 5; 154 } 155 156 buf = utilfdt_read(argv[1]); 157 if (buf) 158 dump_blob(buf); 159 else 160 return 10; 161 162 return 0; 163} 164