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

Archive Download this file

Revision: 840