2 * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved.
8 Structures for a Flattened Device Tree
11 #define kPropNameLength 32
13 typedef struct DeviceTreeNodeProperty
{
14 char name
[kPropNameLength
]; // NUL terminated property name
15 unsigned long length
; // Length (bytes) of folloing prop value
16 // unsigned long value[1]; // Variable length value of property
17 // Padded to a multiple of a longword?
18 } DeviceTreeNodeProperty
;
20 typedef struct OpaqueDTEntry
{
21 unsigned long nProperties
; // Number of props[] elements (0 => end)
22 unsigned long nChildren
; // Number of children[] elements
23 // DeviceTreeNodeProperty props[];// array size == nProperties
24 // DeviceTreeNode children[]; // array size == nChildren
27 typedef char DTPropertyNameBuf
[32];
28 /* Entry Name Definitions (Entry Names are C-Strings)*/
30 kDTMaxEntryNameLength
= 31 /* Max length of a C-String Entry Name (terminator not included) */
33 /* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
34 typedef char DTEntryNameBuf
[32];
38 #include "device_tree.h"
41 #define DPRINTF(args...) printf(args)
43 #define DPRINTF(args...)
48 DT__PrintTree(Node
*node
);
50 #define RoundToLong(x) (((x) + 3) & ~3)
52 static struct _DTSizeInfo
{
54 uint32_t numProperties
;
55 uint32_t totalPropertySize
;
58 #define kAllocSize 4096
60 static Node
*rootNode
;
62 static Node
*freeNodes
, *allocedNodes
;
63 static Property
*freeProperties
, *allocedProperties
;
66 DT__AddProperty(Node
*node
, char *name
, uint32_t length
, void *value
)
70 DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node
), name
, length
, value
);
71 if (freeProperties
== NULL
) {
72 void *buf
= malloc(kAllocSize
);
75 DPRINTF("Allocating more free properties\n");
76 if (buf
== 0) return 0;
77 bzero(buf
, kAllocSize
);
78 // Use the first property to record the allocated buffer
80 prop
= (Property
*)buf
;
81 prop
->next
= allocedProperties
;
82 allocedProperties
= prop
;
85 for (i
=1; i
<(kAllocSize
/ sizeof(Property
)); i
++) {
86 prop
->next
= freeProperties
;
87 freeProperties
= prop
;
91 prop
= freeProperties
;
92 freeProperties
= prop
->next
;
95 prop
->length
= length
;
98 // Always add to end of list
99 if (node
->properties
== 0) {
100 node
->properties
= prop
;
102 node
->last_prop
->next
= prop
;
104 node
->last_prop
= prop
;
107 DPRINTF("Done [0x%x]\n", prop
);
109 DTInfo
.numProperties
++;
110 DTInfo
.totalPropertySize
+= RoundToLong(length
);
116 DT__AddChild(Node
*parent
, char *name
)
120 if (freeNodes
== NULL
) {
121 void *buf
= malloc(kAllocSize
);
124 DPRINTF("Allocating more free nodes\n");
125 if (buf
== 0) return 0;
126 bzero(buf
, kAllocSize
);
128 // Use the first node to record the allocated buffer
129 // for later freeing.
130 node
->next
= allocedNodes
;
132 node
->children
= (Node
*)buf
;
134 for (i
=1; i
<(kAllocSize
/ sizeof(Node
)); i
++) {
135 node
->next
= freeNodes
;
140 DPRINTF("DT__AddChild(0x%x, '%s')\n", parent
, name
);
142 freeNodes
= node
->next
;
143 DPRINTF("Got free node 0x%x\n", node
);
144 DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node
->properties
, node
->children
, node
->next
);
146 if (parent
== NULL
) {
150 node
->next
= parent
->children
;
151 parent
->children
= node
;
154 DT__AddProperty(node
, "name", strlen(name
) + 1, name
);
159 DT__FreeProperty(Property
*prop
)
161 prop
->next
= freeProperties
;
162 freeProperties
= prop
;
165 DT__FreeNode(Node
*node
)
167 node
->next
= freeNodes
;
174 DPRINTF("DT__Initialize\n");
179 allocedProperties
= 0;
182 DTInfo
.numProperties
= 0;
183 DTInfo
.totalPropertySize
= 0;
185 rootNode
= DT__AddChild(NULL
, "/");
186 DPRINTF("DT__Initialize done\n");
190 * Free up memory used by in-memory representation
199 DPRINTF("DT__Finalize\n");
200 for (prop
= allocedProperties
; prop
!= NULL
; prop
= prop
->next
) {
203 allocedProperties
= NULL
;
204 freeProperties
= NULL
;
206 for (node
= allocedNodes
; node
!= NULL
; node
= node
->next
) {
207 free((void *)node
->children
);
213 // XXX leaks any created strings
216 DTInfo
.numProperties
= 0;
217 DTInfo
.totalPropertySize
= 0;
221 FlattenNodes(Node
*node
, void *buffer
)
224 DeviceTreeNode
*flatNode
;
225 DeviceTreeNodeProperty
*flatProp
;
228 if (node
== 0) return buffer
;
230 flatNode
= (DeviceTreeNode
*)buffer
;
231 buffer
+= sizeof(DeviceTreeNode
);
233 for (count
= 0, prop
= node
->properties
; prop
!= 0; count
++, prop
= prop
->next
) {
234 flatProp
= (DeviceTreeNodeProperty
*)buffer
;
235 strcpy(flatProp
->name
, prop
->name
);
236 flatProp
->length
= prop
->length
;
237 buffer
+= sizeof(DeviceTreeNodeProperty
);
238 bcopy(prop
->value
, buffer
, prop
->length
);
239 buffer
+= RoundToLong(prop
->length
);
241 flatNode
->nProperties
= count
;
243 for (count
= 0, node
= node
->children
; node
!= 0; count
++, node
= node
->next
) {
244 buffer
= FlattenNodes(node
, buffer
);
246 flatNode
->nChildren
= count
;
252 * Flatten the in-memory representation of the device tree
253 * into a binary DT block.
254 * To get the buffer size needed, call with result = 0.
255 * To have a buffer allocated for you, call with *result = 0.
256 * To use your own buffer, call with *result = &buffer.
260 DT__FlattenDeviceTree(void **buffer_p
, uint32_t *length
)
265 DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p
, length
);
266 if (buffer_p
) DT__PrintTree(rootNode
);
268 totalSize
= DTInfo
.numNodes
* sizeof(DeviceTreeNode
) +
269 DTInfo
.numProperties
* sizeof(DeviceTreeNodeProperty
) +
270 DTInfo
.totalPropertySize
;
272 DPRINTF("Total size 0x%x\n", totalSize
);
274 if (totalSize
== 0) {
277 if (*buffer_p
== 0) {
278 buf
= malloc(totalSize
);
282 bzero(buf
, totalSize
);
284 FlattenNodes(rootNode
, buf
);
293 DT__GetName(Node
*node
)
297 //DPRINTF("DT__GetName(0x%x)\n", node);
298 //DPRINTF("Node properties = 0x%x\n", node->properties);
299 for (prop
= node
->properties
; prop
; prop
= prop
->next
) {
300 //DPRINTF("Prop '%s'\n", prop->name);
301 if (strcmp(prop
->name
, "name") == 0) {
305 //DPRINTF("DT__GetName returns 0\n");
310 DT__FindNode(char *path
, bool createIfMissing
)
313 DTPropertyNameBuf nameBuf
;
317 DPRINTF("DT__FindNode('%s', %d)\n", path
, createIfMissing
);
321 DPRINTF("root = 0x%x\n", rootNode
);
324 // Skip leading slash
325 while (*path
== '/') path
++;
327 for (i
=0, bp
= nameBuf
; ++i
< kDTMaxEntryNameLength
&& *path
&& *path
!= '/'; bp
++, path
++) *bp
= *path
;
330 if (nameBuf
[0] == '\0') {
334 DPRINTF("Node '%s'\n", nameBuf
);
336 for (child
= node
->children
; child
!= 0; child
= child
->next
) {
337 DPRINTF("Child 0x%x\n", child
);
338 if (strcmp(DT__GetName(child
), nameBuf
) == 0) {
342 if (child
== 0 && createIfMissing
) {
343 DPRINTF("Creating node\n");
344 char *str
= malloc(strlen(nameBuf
) + 1);
345 // XXX this will leak
346 strcpy(str
, nameBuf
);
348 child
= DT__AddChild(node
, str
);
356 DT__PrintNode(Node
*node
, int level
)
358 char spaces
[10], *cp
= spaces
;
361 if (level
> 9) level
= 9;
362 while (level
--) *cp
++ = ' ';
365 printf("%s===Node===\n", spaces
);
366 for (prop
= node
->properties
; prop
; prop
= prop
->next
) {
367 char c
= *((char *)prop
->value
);
368 if (prop
->length
< 64 && (
369 strcmp(prop
->name
, "name") == 0 ||
370 (c
>= '0' && c
<= '9') ||
371 (c
>= 'a' && c
<= 'z') ||
372 (c
>= 'A' && c
<= 'Z') || c
== '_')) {
373 printf("%s Property '%s' [%d] = '%s'\n", spaces
, prop
->name
, prop
->length
, prop
->value
);
375 printf("%s Property '%s' [%d] = (data)\n", spaces
, prop
->name
, prop
->length
);
378 printf("%s==========\n", spaces
);
382 _PrintTree(Node
*node
, int level
)
384 DT__PrintNode(node
, level
);
386 for (node
= node
->children
; node
; node
= node
->next
)
387 _PrintTree(node
, level
);
391 DT__PrintTree(Node
*node
)
393 if (node
== 0) node
= rootNode
;
400 DT__PrintFlattenedNode(DTEntry entry
, int level
)
402 char spaces
[10], *cp
= spaces
;
403 DTPropertyIterator propIter
;
408 if (level
> 9) level
= 9;
409 while (level
--) *cp
++ = ' ';
412 printf("%s===Entry %p===\n", spaces
, entry
);
413 if (kSuccess
!= DTCreatePropertyIterator(entry
, &propIter
)) {
414 printf("Couldn't create property iterator\n");
417 while( kSuccess
== DTIterateProperties( propIter
, &name
)) {
418 if( kSuccess
!= DTGetProperty( entry
, name
, &prop
, &propSize
))
420 printf("%s Property %s = %s\n", spaces
, name
, prop
);
422 DTDisposePropertyIterator(propIter
);
424 printf("%s==========\n", spaces
);
428 _PrintFlattenedTree(DTEntry entry
, int level
)
430 DTEntryIterator entryIter
;
432 PrintFlattenedNode(entry
, level
);
434 if (kSuccess
!= DTCreateEntryIterator(entry
, &entryIter
)) {
435 printf("Couldn't create entry iterator\n");
439 while (kSuccess
== DTIterateEntries( entryIter
, &entry
)) {
440 _PrintFlattenedTree(entry
, level
);
442 DTDisposeEntryIterator(entryIter
);
446 DT__PrintFlattenedTree(DTEntry entry
)
448 _PrintFlattenedTree(entry
, 0);
453 main(int argc
, char **argv
)
456 DTPropertyIterator propIter
;
457 DTEntryIterator entryIter
;
466 node
= AddChild(NULL
, "device-tree");
467 AddProperty(node
, "potato", 4, "foo");
468 AddProperty(node
, "chemistry", 4, "bar");
469 AddProperty(node
, "physics", 4, "baz");
471 node
= AddChild(node
, "dev");
472 AddProperty(node
, "one", 4, "one");
473 AddProperty(node
, "two", 4, "two");
474 AddProperty(node
, "three", 6, "three");
476 node
= AddChild(rootNode
, "foo");
477 AddProperty(node
, "aaa", 4, "aab");
478 AddProperty(node
, "bbb", 4, "bbc");
479 AddProperty(node
, "cccc", 6, "ccccd");
481 node
= FindNode("/this/is/a/test", 1);
482 AddProperty(node
, "dddd", 12, "abcdefghijk");
484 printf("In-memory tree:\n\n");
488 FlattenDeviceTree(&flatTree
, &flatSize
);
490 printf("Flat tree = %p, size %d\n", flatTree
, flatSize
);
492 dtEntry
= (DTEntry
)flatTree
;
494 printf("\n\nPrinting flat tree\n\n");
498 PrintFlattenedTree((DTEntry
)flatTree
);
500 printf("=== Entry %p ===\n", dtEntry
);
501 if (kSuccess
!= DTCreatePropertyIterator(dtEntry
, &propIter
)) {
502 printf("Couldn't create property iterator\n");
505 while( kSuccess
== DTIterateProperties( propIter
, &name
)) {
506 if( kSuccess
!= DTGetProperty( dtEntry
, name
, &prop
, &propSize
))
508 printf(" Property %s = %s\n", name
, prop
);
510 DTDisposePropertyIterator(propIter
);
511 printf("========\n");
513 if (kSuccess
!= DTCreateEntryIterator(dtEntry
, &entryIter
)) {
514 printf("Couldn't create entry iterator\n");
517 while (kSuccess
== DTIterateEntries( entryIter
, &dtEntry
)) {
518 printf("=== Entry %p ===\n", dtEntry
);
520 if (kSuccess
!= DTCreatePropertyIterator(dtEntry
, &propIter
)) {
521 printf("Couldn't create property iterator\n");
524 while( kSuccess
== DTIterateProperties( propIter
, &name
)) {
525 if( kSuccess
!= DTGetProperty( dtEntry
, name
, &prop
, &propSize
))
527 printf(" Property %s = %s\n", name
, prop
);
529 DTDisposePropertyIterator(propIter
);
530 printf("========\n");
532 DTDisposeEntryIterator(entryIter
);