devicetree.c (2409B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 #include <hw/debug.h> 5 #include <hw/riscv.h> 6 #include <hw/devicetree.h> 7 8 #include <string.h> 9 10 static inline uint32_t swap(uint32_t n) { 11 return (n >> 24) | (n << 24) | 12 ((n >> 8) & 0x0000FF00) | 13 ((n << 8) & 0x00FF0000); 14 } 15 16 int isstring(const char* s) { 17 switch (s[0]) { 18 case 'b': 19 if (!strcmp(s, "bootargs")) return 1; 20 case 'c': 21 if (!strcmp(s, "compatible")) return 1; 22 break; 23 case 'd': 24 if (!strcmp(s, "device_type")) return 1; 25 break; 26 case 'm': 27 if (!strcmp(s, "model")) return 1; 28 if (!strcmp(s, "mmu-type")) return 1; 29 break; 30 case 'r': 31 if (!strcmp(s, "riscv.isa")) return 1; 32 break; 33 } 34 return 0; 35 } 36 37 void xindent(unsigned count) { 38 while (count-- > 0) { 39 xputs(" "); 40 } 41 } 42 43 void fdt_walk(fdt_header_t* fdt) { 44 uint32_t* data = (void*) (((uintptr_t) fdt) + swap(fdt->off_dt_struct)); 45 char* strtab = (char*) (((uintptr_t) fdt) + swap(fdt->off_dt_strings)); 46 unsigned indent = 0; 47 for (;;) { 48 switch(swap(*data++)) { 49 case FDT_PADDING: 50 case FDT_NOP: 51 continue; 52 case FDT_BEGIN_NODE: { 53 char *name = (void*) data; 54 uint32_t len = strlen(name) + 1; 55 xindent(indent); 56 xprintf("NODE '%s'\n", name); 57 indent++; 58 data += ((len + 3) >> 2); 59 break; 60 } 61 case FDT_END_NODE: 62 indent--; 63 break; 64 case FDT_PROP: { 65 uint32_t len = swap(*data++); 66 uint32_t name = swap(*data++); 67 xindent(indent); 68 xprintf("PROP '%s' %u:", strtab + name, len); 69 if (isstring(strtab + name)) { 70 xprintf(" '%s'\n", (char*) data); 71 } else { 72 for (unsigned n = 0; n < len; n++) { 73 xprintf(" %02x", ((uint8_t*)data)[n]); 74 } 75 xprintf("\n"); 76 } 77 data += ((len + 3) >> 2); 78 break; 79 } 80 default: 81 xprintf("HUH %08x\n", swap(data[-1])); 82 return; 83 case FDT_END: 84 xprintf("END\n"); 85 return; 86 } 87 } 88 } 89 90 void start(unsigned _, fdt_header_t* fdt) { 91 xprintf("fdt %p\n", fdt); 92 xprintf("fdt.magic %08x\n", swap(fdt->magic)); 93 xprintf("fdt.version %08x\n", swap(fdt->version)); 94 xprintf("fdt.struct %08x %08x\n", 95 swap(fdt->off_dt_struct), swap(fdt->size_dt_struct)); 96 xprintf("fdt.strings %08x %08x\n", 97 swap(fdt->off_dt_strings), swap(fdt->size_dt_strings)); 98 99 fdt_walk(fdt); 100 101 for (unsigned n = 0x10001000; n < 0x10009000; n+= 0x1000) { 102 unsigned *x = (void*) n; 103 xprintf("%08x: %08x %08x %08x %08x\n", 104 n, x[0], x[1], x[2], x[3]); 105 } 106 }