Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/device_tree.c

1/*
2 * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved.
3 */
4
5#if 1
6/*
7
8 Structures for a Flattened Device Tree
9 */
10
11#define kPropNameLength 32
12
13typedef 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;
19
20typedef 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
25} DeviceTreeNode;
26
27typedef char DTPropertyNameBuf[32];
28/* Entry Name Definitions (Entry Names are C-Strings)*/
29enum {
30 kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */
31};
32
33/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
34typedef char DTEntryNameBuf[32];
35#endif
36
37#include "libsaio.h"
38#include "device_tree.h"
39
40#if DEBUG
41#define DPRINTF(args...) printf(args)
42void
43DT__PrintTree(Node *node);
44#else
45#define DPRINTF(args...)
46#endif
47
48
49#define RoundToLong(x)(((x) + 3) & ~3)
50
51static struct _DTSizeInfo {
52 uint32_t numNodes;
53 uint32_t numProperties;
54 uint32_t totalPropertySize;
55} DTInfo;
56
57#define kAllocSize 4096
58
59static Node *rootNode;
60
61static Node *freeNodes, *allocedNodes;
62static Property *freeProperties, *allocedProperties;
63Property *
64DT__AddProperty(Node *node, const char *name, uint32_t length, void *value)
65{
66 Property *prop;
67
68 DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value);
69 if (freeProperties == NULL) {
70 void *buf = malloc(kAllocSize);
71 int i;
72
73 DPRINTF("Allocating more free properties\n");
74 if (buf == 0) return 0;
75 bzero(buf, kAllocSize);
76 // Use the first property to record the allocated buffer
77 // for later freeing.
78 prop = (Property *)buf;
79 prop->next = allocedProperties;
80 allocedProperties = prop;
81 prop->value = buf;
82 prop++;
83 for (i=1; (unsigned)i<(kAllocSize / sizeof(Property)); i++) {
84 prop->next = freeProperties;
85 freeProperties = prop;
86 prop++;
87 }
88 }
89 prop = freeProperties;
90 freeProperties = prop->next;
91
92 prop->name = name;
93 prop->length = length;
94 prop->value = value;
95
96 // Always add to end of list
97 if (node->properties == 0) {
98 node->properties = prop;
99 } else {
100 node->last_prop->next = prop;
101 }
102 node->last_prop = prop;
103 prop->next = 0;
104
105 DPRINTF("Done [0x%x]\n", prop);
106
107 DTInfo.numProperties++;
108 DTInfo.totalPropertySize += RoundToLong(length);
109
110 return prop;
111}
112
113Node *
114DT__AddChild(Node *parent, const char *name)
115{
116 Node *node;
117
118 if (freeNodes == NULL) {
119 void *buf = malloc(kAllocSize);
120 int i;
121
122 DPRINTF("Allocating more free nodes\n");
123 if (buf == 0) return 0;
124 bzero(buf, kAllocSize);
125 node = (Node *)buf;
126 // Use the first node to record the allocated buffer
127 // for later freeing.
128 node->next = allocedNodes;
129 allocedNodes = node;
130 node->children = (Node *)buf;
131 node++;
132 for (i=1; (unsigned)i<(kAllocSize / sizeof(Node)); i++) {
133 node->next = freeNodes;
134 freeNodes = node;
135 node++;
136 }
137 }
138 DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name);
139 node = freeNodes;
140 freeNodes = node->next;
141 DPRINTF("Got free node 0x%x\n", node);
142 DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next);
143
144 if (parent == NULL) {
145 rootNode = node;
146 node->next = 0;
147 } else {
148 node->next = parent->children;
149 parent->children = node;
150 }
151 DTInfo.numNodes++;
152 DT__AddProperty(node, "name", strlen(name) + 1, (void *) name);
153 return node;
154}
155
156void
157DT__FreeProperty(Property *prop)
158{
159 prop->next = freeProperties;
160 freeProperties = prop;
161}
162void
163DT__FreeNode(Node *node)
164{
165 node->next = freeNodes;
166 freeNodes = node;
167}
168
169void
170DT__Initialize(void)
171{
172 DPRINTF("DT__Initialize\n");
173
174 freeNodes = 0;
175 allocedNodes = 0;
176 freeProperties = 0;
177 allocedProperties = 0;
178
179 DTInfo.numNodes = 0;
180 DTInfo.numProperties = 0;
181 DTInfo.totalPropertySize = 0;
182
183 rootNode = DT__AddChild(NULL, "/");
184 DPRINTF("DT__Initialize done\n");
185}
186
187/*
188 * Free up memory used by in-memory representation
189 * of device tree.
190 */
191void
192DT__Finalize(void)
193{
194 Node *node;
195 Property *prop;
196
197 DPRINTF("DT__Finalize\n");
198 for (prop = allocedProperties; prop != NULL; prop = prop->next) {
199 free(prop->value);
200 }
201 allocedProperties = NULL;
202 freeProperties = NULL;
203
204 for (node = allocedNodes; node != NULL; node = node->next) {
205 free((void *)node->children);
206 }
207 allocedNodes = NULL;
208 freeNodes = NULL;
209 rootNode = NULL;
210
211 // XXX leaks any created strings
212
213 DTInfo.numNodes = 0;
214 DTInfo.numProperties = 0;
215 DTInfo.totalPropertySize = 0;
216}
217
218static void *
219FlattenNodes(Node *node, void *buffer)
220{
221 Property *prop;
222 DeviceTreeNode *flatNode;
223 DeviceTreeNodeProperty *flatProp;
224 int count;
225
226 if (node == 0) return buffer;
227
228 flatNode = (DeviceTreeNode *)buffer;
229 buffer += sizeof(DeviceTreeNode);
230
231 for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next) {
232 flatProp = (DeviceTreeNodeProperty *)buffer;
233 strcpy(flatProp->name, prop->name);
234 flatProp->length = prop->length;
235 buffer += sizeof(DeviceTreeNodeProperty);
236 bcopy(prop->value, buffer, prop->length);
237 buffer += RoundToLong(prop->length);
238 }
239 flatNode->nProperties = count;
240
241 for (count = 0, node = node->children; node != 0; count++, node = node->next) {
242 buffer = FlattenNodes(node, buffer);
243 }
244 flatNode->nChildren = count;
245
246 return buffer;
247}
248
249/*
250 * Flatten the in-memory representation of the device tree
251 * into a binary DT block.
252 * To get the buffer size needed, call with result = 0.
253 * To have a buffer allocated for you, call with *result = 0.
254 * To use your own buffer, call with *result = &buffer.
255 */
256
257void
258DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)
259{
260 uint32_t totalSize;
261 void *buf;
262
263 DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);
264#if DEBUG
265 if (buffer_p) DT__PrintTree(rootNode);
266#endif
267
268 totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) +
269 DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) +
270 DTInfo.totalPropertySize;
271
272 DPRINTF("Total size 0x%x\n", totalSize);
273 if (buffer_p != 0) {
274 if (totalSize == 0) {
275 buf = 0;
276 } else {
277 if (*buffer_p == 0) {
278 buf = malloc(totalSize);
279 } else {
280 buf = *buffer_p;
281 }
282 bzero(buf, totalSize);
283
284 FlattenNodes(rootNode, buf);
285 }
286 *buffer_p = buf;
287 }
288 if (length)
289 *length = totalSize;
290}
291
292char *
293DT__GetName(Node *node)
294{
295 Property *prop;
296
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) {
302 return prop->value;
303 }
304 }
305 //DPRINTF("DT__GetName returns 0\n");
306 return "(null)";
307}
308
309Node *
310DT__FindNode(const char *path, bool createIfMissing)
311{
312 Node *node, *child;
313 DTPropertyNameBuf nameBuf;
314 char *bp;
315 int i;
316
317 DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
318
319 // Start at root
320 node = rootNode;
321 DPRINTF("root = 0x%x\n", rootNode);
322
323 while (node) {
324 // Skip leading slash
325 while (*path == '/') path++;
326
327 for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path;
328 *bp = '\0';
329
330 if (nameBuf[0] == '\0') {
331 // last path entry
332 break;
333 }
334 DPRINTF("Node '%s'\n", nameBuf);
335
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) {
339 break;
340 }
341 }
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);
347
348 child = DT__AddChild(node, str);
349 }
350 node = child;
351 }
352 return node;
353}
354
355#if DEBUG
356
357void
358DT__PrintNode(Node *node, int level)
359{
360 char spaces[10], *cp = spaces;
361 Property *prop;
362
363 if (level > 9) level = 9;
364 while (level--) *cp++ = ' ';
365 *cp = '\0';
366
367 printf("%s===Node===\n", spaces);
368 for (prop = node->properties; prop; prop = prop->next) {
369 char c = *((char *)prop->value);
370 if (prop->length < 64 && (
371 strcmp(prop->name, "name") == 0 ||
372 (c >= '0' && c <= '9') ||
373 (c >= 'a' && c <= 'z') ||
374 (c >= 'A' && c <= 'Z') || c == '_')) {
375 printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
376 } else {
377 printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
378 }
379 }
380 printf("%s==========\n", spaces);
381}
382
383static void
384_PrintTree(Node *node, int level)
385{
386 DT__PrintNode(node, level);
387 level++;
388 for (node = node->children; node; node = node->next)
389 _PrintTree(node, level);
390}
391
392void
393DT__PrintTree(Node *node)
394{
395 if (node == 0) node = rootNode;
396 _PrintTree(node, 0);
397}
398
399void
400DT__PrintFlattenedNode(DTEntry entry, int level)
401{
402 char spaces[10], *cp = spaces;
403 DTPropertyIterator propIter;
404 char *name;
405 void *prop;
406 int propSize;
407
408 if (level > 9) level = 9;
409 while (level--) *cp++ = ' ';
410 *cp = '\0';
411
412 printf("%s===Entry %p===\n", spaces, entry);
413 if (kSuccess != DTCreatePropertyIterator(entry, &propIter)) {
414 printf("Couldn't create property iterator\n");
415 return;
416 }
417 while( kSuccess == DTIterateProperties( propIter, &name)) {
418 if( kSuccess != DTGetProperty( entry, name, &prop, &propSize ))
419 continue;
420 printf("%s Property %s = %s\n", spaces, name, prop);
421 }
422 DTDisposePropertyIterator(propIter);
423
424 printf("%s==========\n", spaces);
425}
426
427static void
428_PrintFlattenedTree(DTEntry entry, int level)
429{
430 DTEntryIterator entryIter;
431
432 PrintFlattenedNode(entry, level);
433
434 if (kSuccess != DTCreateEntryIterator(entry, &entryIter)) {
435 printf("Couldn't create entry iterator\n");
436 return;
437 }
438 level++;
439 while (kSuccess == DTIterateEntries( entryIter, &entry )) {
440 _PrintFlattenedTree(entry, level);
441 }
442 DTDisposeEntryIterator(entryIter);
443}
444
445void
446DT__PrintFlattenedTree(DTEntry entry)
447{
448 _PrintFlattenedTree(entry, 0);
449}
450
451#if UNUSED
452int
453main(int argc, char **argv)
454{
455 DTEntry dtEntry;
456 DTPropertyIterator propIter;
457 DTEntryIterator entryIter;
458 void*prop;
459 intpropSize;
460 char*name;
461 void *flatTree;
462 uint32_t flatSize;
463
464 Node *node;
465
466 node = AddChild(NULL, "device-tree");
467 AddProperty(node, "potato", 4, "foo");
468 AddProperty(node, "chemistry", 4, "bar");
469 AddProperty(node, "physics", 4, "baz");
470
471 node = AddChild(node, "dev");
472 AddProperty(node, "one", 4, "one");
473 AddProperty(node, "two", 4, "two");
474 AddProperty(node, "three", 6, "three");
475
476 node = AddChild(rootNode, "foo");
477 AddProperty(node, "aaa", 4, "aab");
478 AddProperty(node, "bbb", 4, "bbc");
479 AddProperty(node, "cccc", 6, "ccccd");
480
481 node = FindNode("/this/is/a/test", 1);
482 AddProperty(node, "dddd", 12, "abcdefghijk");
483
484 printf("In-memory tree:\n\n");
485
486 PrintTree(rootNode);
487
488 FlattenDeviceTree(&flatTree, &flatSize);
489
490 printf("Flat tree = %p, size %d\n", flatTree, flatSize);
491
492 dtEntry = (DTEntry)flatTree;
493
494 printf("\n\nPrinting flat tree\n\n");
495
496 DTInit(dtEntry);
497
498 PrintFlattenedTree((DTEntry)flatTree);
499#if 0
500 printf("=== Entry %p ===\n", dtEntry);
501 if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {
502 printf("Couldn't create property iterator\n");
503 return 1;
504 }
505 while( kSuccess == DTIterateProperties( propIter, &name)) {
506 if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
507 continue;
508 printf(" Property %s = %s\n", name, prop);
509 }
510 DTDisposePropertyIterator(propIter);
511 printf("========\n");
512
513 if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter)) {
514 printf("Couldn't create entry iterator\n");
515 return 1;
516 }
517 while (kSuccess == DTIterateEntries( entryIter, &dtEntry )) {
518 printf("=== Entry %p ===\n", dtEntry);
519
520 if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {
521 printf("Couldn't create property iterator\n");
522 return 1;
523 }
524 while( kSuccess == DTIterateProperties( propIter, &name)) {
525 if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
526 continue;
527 printf(" Property %s = %s\n", name, prop);
528 }
529 DTDisposePropertyIterator(propIter);
530 printf("========\n");
531 }
532 DTDisposeEntryIterator(entryIter);
533#endif
534
535 return 0;
536}
537#endif
538
539#endif
540
541

Archive Download this file

Revision: 1119