1204431Sraj/* 2204431Sraj * ftdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com> 3204431Sraj */ 4204431Sraj 5204431Sraj#include <stdint.h> 6204431Sraj#include <stdio.h> 7204433Sraj#include <stdlib.h> 8204431Sraj#include <string.h> 9204431Sraj#include <ctype.h> 10204431Sraj 11204431Sraj#include <fdt.h> 12204431Sraj#include <libfdt_env.h> 13204431Sraj 14204433Sraj#define FTDUMP_BUF_SIZE 65536 15204433Sraj 16204431Sraj#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 17204431Sraj#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) 18204433Sraj#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) 19204431Sraj 20204431Srajstatic int is_printable_string(const void *data, int len) 21204431Sraj{ 22204431Sraj const char *s = data; 23204431Sraj const char *ss; 24204431Sraj 25204431Sraj /* zero length is not */ 26204431Sraj if (len == 0) 27204431Sraj return 0; 28204431Sraj 29204431Sraj /* must terminate with zero */ 30204431Sraj if (s[len - 1] != '\0') 31204431Sraj return 0; 32204431Sraj 33204431Sraj ss = s; 34204431Sraj while (*s && isprint(*s)) 35204431Sraj s++; 36204431Sraj 37204431Sraj /* not zero, or not done yet */ 38204431Sraj if (*s != '\0' || (s + 1 - ss) < len) 39204431Sraj return 0; 40204431Sraj 41204431Sraj return 1; 42204431Sraj} 43204431Sraj 44204433Srajstatic void print_data(const char *data, int len) 45204431Sraj{ 46204431Sraj int i; 47204433Sraj const char *p = data; 48204431Sraj 49204431Sraj /* no data, don't print */ 50204431Sraj if (len == 0) 51204431Sraj return; 52204431Sraj 53204431Sraj if (is_printable_string(data, len)) { 54204431Sraj printf(" = \"%s\"", (const char *)data); 55204431Sraj } else if ((len % 4) == 0) { 56204431Sraj printf(" = <"); 57204431Sraj for (i = 0; i < len; i += 4) 58204433Sraj printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), 59204431Sraj i < (len - 4) ? " " : ""); 60204431Sraj printf(">"); 61204431Sraj } else { 62204431Sraj printf(" = ["); 63204433Sraj for (i = 0; i < len; i++) 64204433Sraj printf("%02x%s", *p++, i < len - 1 ? " " : ""); 65204431Sraj printf("]"); 66204431Sraj } 67204431Sraj} 68204431Sraj 69204431Srajstatic void dump_blob(void *blob) 70204431Sraj{ 71204431Sraj struct fdt_header *bph = blob; 72204431Sraj uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); 73204431Sraj uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); 74204431Sraj uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); 75204431Sraj struct fdt_reserve_entry *p_rsvmap = 76204431Sraj (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); 77204433Sraj const char *p_struct = (const char *)blob + off_dt; 78204433Sraj const char *p_strings = (const char *)blob + off_str; 79204431Sraj uint32_t version = fdt32_to_cpu(bph->version); 80204431Sraj uint32_t totalsize = fdt32_to_cpu(bph->totalsize); 81204431Sraj uint32_t tag; 82204433Sraj const char *p, *s, *t; 83204431Sraj int depth, sz, shift; 84204431Sraj int i; 85204431Sraj uint64_t addr, size; 86204431Sraj 87204431Sraj depth = 0; 88204431Sraj shift = 4; 89204431Sraj 90204433Sraj printf("/dts-v1/;\n"); 91204431Sraj printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); 92204431Sraj printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); 93204431Sraj printf("// off_dt_struct:\t0x%x\n", off_dt); 94204431Sraj printf("// off_dt_strings:\t0x%x\n", off_str); 95204431Sraj printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); 96204431Sraj printf("// version:\t\t%d\n", version); 97204431Sraj printf("// last_comp_version:\t%d\n", 98204431Sraj fdt32_to_cpu(bph->last_comp_version)); 99204431Sraj if (version >= 2) 100204431Sraj printf("// boot_cpuid_phys:\t0x%x\n", 101204431Sraj fdt32_to_cpu(bph->boot_cpuid_phys)); 102204431Sraj 103204431Sraj if (version >= 3) 104204431Sraj printf("// size_dt_strings:\t0x%x\n", 105204431Sraj fdt32_to_cpu(bph->size_dt_strings)); 106204431Sraj if (version >= 17) 107204431Sraj printf("// size_dt_struct:\t0x%x\n", 108204431Sraj fdt32_to_cpu(bph->size_dt_struct)); 109204431Sraj printf("\n"); 110204431Sraj 111204431Sraj for (i = 0; ; i++) { 112204431Sraj addr = fdt64_to_cpu(p_rsvmap[i].address); 113204431Sraj size = fdt64_to_cpu(p_rsvmap[i].size); 114204431Sraj if (addr == 0 && size == 0) 115204431Sraj break; 116204431Sraj 117204431Sraj printf("/memreserve/ %llx %llx;\n", 118204431Sraj (unsigned long long)addr, (unsigned long long)size); 119204431Sraj } 120204431Sraj 121204431Sraj p = p_struct; 122204431Sraj while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { 123204431Sraj 124204431Sraj /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ 125204431Sraj 126204431Sraj if (tag == FDT_BEGIN_NODE) { 127204431Sraj s = p; 128204431Sraj p = PALIGN(p + strlen(s) + 1, 4); 129204431Sraj 130204431Sraj if (*s == '\0') 131204431Sraj s = "/"; 132204431Sraj 133204431Sraj printf("%*s%s {\n", depth * shift, "", s); 134204431Sraj 135204431Sraj depth++; 136204431Sraj continue; 137204431Sraj } 138204431Sraj 139204431Sraj if (tag == FDT_END_NODE) { 140204431Sraj depth--; 141204431Sraj 142204431Sraj printf("%*s};\n", depth * shift, ""); 143204431Sraj continue; 144204431Sraj } 145204431Sraj 146204431Sraj if (tag == FDT_NOP) { 147204431Sraj printf("%*s// [NOP]\n", depth * shift, ""); 148204431Sraj continue; 149204431Sraj } 150204431Sraj 151204431Sraj if (tag != FDT_PROP) { 152204431Sraj fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); 153204431Sraj break; 154204431Sraj } 155204431Sraj sz = fdt32_to_cpu(GET_CELL(p)); 156204431Sraj s = p_strings + fdt32_to_cpu(GET_CELL(p)); 157204431Sraj if (version < 16 && sz >= 8) 158204431Sraj p = PALIGN(p, 8); 159204431Sraj t = p; 160204431Sraj 161204431Sraj p = PALIGN(p + sz, 4); 162204431Sraj 163204431Sraj printf("%*s%s", depth * shift, "", s); 164204431Sraj print_data(t, sz); 165204431Sraj printf(";\n"); 166204431Sraj } 167204431Sraj} 168204431Sraj 169204431Sraj 170204431Srajint main(int argc, char *argv[]) 171204431Sraj{ 172204431Sraj FILE *fp; 173204433Sraj char *buf; 174204431Sraj int size; 175204431Sraj 176204431Sraj if (argc < 2) { 177204431Sraj fprintf(stderr, "supply input filename\n"); 178204431Sraj return 5; 179204431Sraj } 180204431Sraj 181204433Sraj if (strcmp(argv[1], "-") == 0) { 182204433Sraj fp = stdin; 183204433Sraj } else { 184204433Sraj fp = fopen(argv[1], "rb"); 185204433Sraj if (fp == NULL) { 186204433Sraj fprintf(stderr, "unable to open %s\n", argv[1]); 187204433Sraj return 10; 188204433Sraj } 189204433Sraj } 190204433Sraj 191204433Sraj buf = malloc(FTDUMP_BUF_SIZE); 192204433Sraj if (!buf) { 193204433Sraj fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE); 194204431Sraj return 10; 195204431Sraj } 196204431Sraj 197204433Sraj size = fread(buf, 1, FTDUMP_BUF_SIZE, fp); 198204433Sraj if (size == FTDUMP_BUF_SIZE) { 199204433Sraj fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE); 200204431Sraj return 10; 201204431Sraj } 202204431Sraj 203204431Sraj dump_blob(buf); 204204431Sraj 205204431Sraj fclose(fp); 206204431Sraj 207204431Sraj return 0; 208204431Sraj} 209