Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1207