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

Archive Download this file

Revision: 495