Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1985