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

Archive Download this file

Revision: 1804