Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 515