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