revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / arch / arm-raspi / boot / devicetree.c
blobcf90d876cd0fbcbd39dc6f18da0438b1413443ff
1 #include <aros/macros.h>
2 #include "devicetree.h"
3 #include "boot.h"
4 #include <stdlib.h>
5 #include <string.h>
7 #define D(x)
9 of_node_t *root = NULL;
10 uint32_t *data;
11 char *strings;
13 of_node_t * dt_build_node(of_node_t *parent)
15 of_node_t *e = malloc(sizeof(of_node_t));
17 if (e != NULL)
19 if (parent != NULL)
21 ADDTAIL(&parent->on_children, e);
23 NEWLIST(&e->on_children);
24 NEWLIST(&e->on_properties);
25 e->on_name = (char *)data;
26 data += (strlen((char *)data) + 4) / 4;
28 D(kprintf("[BOOT] new node %s\n", e->on_name));
30 while(1)
32 switch (AROS_BE2LONG(*data++))
34 case FDT_BEGIN_NODE:
36 dt_build_node(e);
37 break;
40 case FDT_PROP:
42 of_property_t *p = malloc(sizeof(of_property_t));
43 p->op_length = AROS_BE2LONG(*data++);
44 p->op_name = &strings[AROS_BE2LONG(*data++)];
45 if (p->op_length)
46 p->op_value = data;
47 else
48 p->op_value = NULL;
49 ADDTAIL(&e->on_properties, p);
50 data += (p->op_length + 3)/4;
51 D(kprintf("[BOOT] prop %s with length %d\n", p->op_name, p->op_length));
52 break;
55 case FDT_NOP:
56 break;
58 case FDT_END_NODE:
59 return e;
63 return e;
66 static struct fdt_header *hdr;
68 long dt_total_size()
70 if (hdr != NULL)
71 return AROS_BE2LONG(hdr->totalsize);
72 else
73 return 0;
76 of_node_t * dt_parse(void *dt)
78 uint32_t token = 0;
80 hdr = dt;
82 D(kprintf("[BOOT] Checking device tree at %p\n", hdr));
83 D(kprintf("[BOOT] magic=%08x\n", AROS_LONG2BE(hdr->magic)));
85 if (hdr->magic == AROS_LONG2BE(FDT_MAGIC))
87 D(kprintf("[BOOT] Appears to be a valid device tree\n"));
88 D(kprintf("[BOOT] size=%d\n", AROS_BE2LONG(hdr->totalsize)));
89 D(kprintf("[BOOT] off_dt_struct=%d\n", AROS_BE2LONG(hdr->off_dt_struct)));
90 D(kprintf("[BOOT] off_dt_strings=%d\n", AROS_BE2LONG(hdr->off_dt_strings)));
91 D(kprintf("[BOOT] off_mem_rsvmap=%d\n", AROS_BE2LONG(hdr->off_mem_rsvmap)));
93 strings = dt + AROS_BE2LONG(hdr->off_dt_strings);
94 data = dt + AROS_BE2LONG(hdr->off_dt_struct);
96 if (hdr->off_mem_rsvmap)
98 struct fdt_reserve_entry *rsrvd = dt + AROS_BE2LONG(hdr->off_mem_rsvmap);
100 while (rsrvd->address != 0 || rsrvd->size != 0) {
101 D(kprintf("[BOOT] reserved: %08x-%08x\n",
102 (uint32_t)AROS_BE2QUAD(rsrvd->address),
103 (uint32_t)(AROS_BE2QUAD(rsrvd->address) + AROS_BE2QUAD(rsrvd->size - 1)))
105 rsrvd++;
111 token = AROS_BE2LONG(*data++);
113 switch (token)
115 case FDT_BEGIN_NODE:
116 root = dt_build_node(NULL);
117 break;
118 case FDT_PROP:
120 kprintf("[BOOT] Property outside root node?");
121 break;
124 } while (token != FDT_END);
126 else
128 hdr = NULL;
131 return root;
134 static of_node_t * dt_find_by_phandle(uint32_t phandle, of_node_t *root)
136 of_property_t *p = dt_find_property(root, "phandle");
138 if (p && *((uint32_t *)p->op_value) == AROS_LONG2BE(phandle))
139 return root;
140 else {
141 of_node_t *c;
142 ForeachNode(&root->on_children, c)
144 of_node_t *found = dt_find_by_phandle(phandle, c);
145 if (found)
146 return found;
149 return NULL;
152 of_node_t * dt_find_node_by_phandle(uint32_t phandle)
154 return dt_find_by_phandle(phandle, root);
157 #define MAX_KEY_SIZE 64
158 char ptrbuf[64];
160 of_node_t * dt_find_node(char *key)
162 int i;
163 of_node_t *node, *ret = NULL;
165 if (*key == '/')
167 ret = root;
169 while(*key)
171 key++;
172 for (i=0; i < 63; i++)
174 if (*key == '/' || *key == 0)
175 break;
176 ptrbuf[i] = *key;
177 key++;
180 ptrbuf[i] = 0;
182 ForeachNode(&ret->on_children, node)
184 if (!strcmp(node->on_name, ptrbuf))
186 ret = node;
187 break;
193 return ret;
196 of_property_t *dt_find_property(void *key, char *propname)
198 of_node_t *node = (of_node_t *)key;
199 of_property_t *p, *prop = NULL;
201 if (node)
203 ForeachNode(&node->on_properties, p)
205 if (!strcmp(p->op_name, propname))
207 prop = p;
208 break;
212 return prop;
215 char fill[] = " ";
217 void dt_dump_node(of_node_t *n, int level)
219 of_property_t *p;
220 of_node_t *c;
222 kprintf("[BOOT] %s%s\n", &fill[25-2*level], n->on_name);
223 ForeachNode(&n->on_properties, p)
225 kprintf("[BOOT] %s %s=", &fill[25-2*level], p->op_name);
226 for (int i=0; i < p->op_length; i++) {
227 char *pchar = p->op_value + i;
228 if (*pchar >= ' ' && *pchar <= 'z')
229 kprintf("%c", *pchar);
230 else
231 kprintf(".");
234 if (p->op_length) {
235 kprintf(" (");
236 int max = 16;
237 if (max > p->op_length)
238 max = p->op_length;
240 for (int i=0; i < p->op_length; i++) {
241 char *pchar = p->op_value + i;
242 kprintf("%02x", *pchar);
244 kprintf(")");
246 kprintf("\n");
249 ForeachNode(&n->on_children, c)
251 dt_dump_node(c, level+1);
255 void dt_dump_tree()
257 kprintf("[BOOT] Device Tree dump:\n");
259 dt_dump_node(root, 0);