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 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#if 1
26/*
27
28 Structures for a Flattened Device Tree
29 */
30
31#define kPropNameLength 32
32
33typedef struct DeviceTreeNodeProperty
34{
35char name[kPropNameLength]; // NUL terminated property name
36unsigned long length; // Length (bytes) of folloing prop value
37 // unsigned long value[1]; // Variable length value of property
38 // Padded to a multiple of a longword?
39} DeviceTreeNodeProperty;
40
41typedef struct OpaqueDTEntry
42{
43unsigned long nProperties; // Number of props[] elements (0 => end)
44unsigned long nChildren; // Number of children[] elements
45 // DeviceTreeNodeProperty props[];// array size == nProperties
46 // DeviceTreeNode children[]; // array size == nChildren
47} DeviceTreeNode;
48
49typedef char DTPropertyNameBuf[32];
50
51// Entry Name Definitions (Entry Names are C-Strings).
52enum {
53 kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */
54};
55
56/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
57typedef char DTEntryNameBuf[32];
58#endif
59
60#include "libsaio.h"
61#include "device_tree.h"
62
63#if DEBUG
64#define DPRINTF(args...) printf(args)
65void
66DT__PrintTree(Node *node);
67#else
68#define DPRINTF(args...)
69#endif
70
71
72#define RoundToLong(x)(((x) + 3) & ~3)
73
74static struct _DTSizeInfo
75{
76uint32_tnumNodes;
77uint32_tnumProperties;
78uint32_ttotalPropertySize;
79} DTInfo;
80
81#define kAllocSize 4096
82
83static Node *rootNode;
84
85static Node * freeNodes, *allocedNodes;
86static Property *freeProperties, *allocedProperties;
87
88
89//==============================================================================
90
91Property * DT__AddProperty(Node *node, const char *name, uint32_t length, void *value)
92{
93Property *prop;
94
95DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value);
96
97if (freeProperties == NULL)
98{
99void *buf = malloc(kAllocSize);
100int i;
101
102DPRINTF("Allocating more free properties\n");
103
104if (buf == 0)
105{
106return 0;
107}
108
109bzero(buf, kAllocSize);
110// Use the first property to record the allocated buffer
111// for later freeing.
112prop = (Property *)buf;
113prop->next = allocedProperties;
114allocedProperties = prop;
115prop->value = buf;
116prop++;
117
118for (i = 1; i < (kAllocSize / sizeof(Property)); i++)
119{
120prop->next = freeProperties;
121freeProperties = prop;
122prop++;
123}
124}
125
126prop = freeProperties;
127freeProperties = prop->next;
128
129prop->name = name;
130prop->length = length;
131prop->value = value;
132
133// Always add to end of list
134if (node->properties == 0)
135{
136node->properties = prop;
137}
138else
139{
140node->last_prop->next = prop;
141}
142
143node->last_prop = prop;
144prop->next = 0;
145
146DPRINTF("Done [0x%x]\n", prop);
147
148DTInfo.numProperties++;
149DTInfo.totalPropertySize += RoundToLong(length);
150
151return prop;
152}
153
154
155//==============================================================================
156
157Node * DT__AddChild(Node *parent, const char *name)
158{
159Node *node;
160
161if (freeNodes == NULL)
162{
163void *buf = malloc(kAllocSize);
164
165if (buf == 0)
166{
167return 0;
168}
169
170int i;
171
172DPRINTF("Allocating more free nodes\n");
173
174bzero(buf, kAllocSize);
175node = (Node *)buf;
176
177// Use the first node to record the allocated buffer for later freeing.
178node->next = allocedNodes;
179allocedNodes = node;
180node->children = (Node *)buf;
181node++;
182
183for (i = 1; i < (kAllocSize / sizeof(Node)); i++)
184{
185node->next = freeNodes;
186freeNodes = node;
187node++;
188}
189}
190
191DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name);
192
193node = freeNodes;
194freeNodes = node->next;
195
196DPRINTF("Got free node 0x%x\n", node);
197DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next);
198
199if (parent == NULL)
200{
201rootNode = node;
202node->next = 0;
203}
204else
205{
206node->next = parent->children;
207parent->children = node;
208}
209
210DTInfo.numNodes++;
211DT__AddProperty(node, "name", strlen(name) + 1, (void *) name);
212
213return node;
214}
215
216
217//==============================================================================
218
219void DT__FreeProperty(Property *prop)
220{
221prop->next = freeProperties;
222freeProperties = prop;
223}
224
225
226//==============================================================================
227
228void DT__FreeNode(Node *node)
229{
230node->next = freeNodes;
231freeNodes = node;
232}
233
234
235//==============================================================================
236
237void DT__Initialize(void)
238{
239DPRINTF("DT__Initialize\n");
240
241freeNodes = 0;
242allocedNodes = 0;
243freeProperties = 0;
244allocedProperties = 0;
245
246DTInfo.numNodes = 0;
247DTInfo.numProperties = 0;
248DTInfo.totalPropertySize = 0;
249
250rootNode = DT__AddChild(NULL, "/");
251DPRINTF("DT__Initialize done\n");
252}
253
254//==============================================================================
255/*
256 * Free up memory used by in-memory representation of device tree.
257 */
258void DT__Finalize(void)
259{
260Node *node;
261Property *prop;
262
263DPRINTF("DT__Finalize\n");
264
265for (prop = allocedProperties; prop != NULL; prop = prop->next)
266{
267free(prop->value);
268}
269
270allocedProperties = NULL;
271freeProperties = NULL;
272
273for (node = allocedNodes; node != NULL; node = node->next)
274{
275free((void *)node->children);
276}
277
278allocedNodes = NULL;
279freeNodes = NULL;
280rootNode = NULL;
281
282// XXX leaks any created strings
283DTInfo.numNodes = 0;
284DTInfo.numProperties = 0;
285DTInfo.totalPropertySize = 0;
286}
287
288
289//==============================================================================
290
291static void * FlattenNodes(Node *node, void *buffer)
292{
293Property *prop;
294DeviceTreeNode *flatNode;
295DeviceTreeNodeProperty *flatProp;
296int count;
297
298if (node == 0)
299{
300return buffer;
301}
302
303flatNode = (DeviceTreeNode *)buffer;
304buffer += sizeof(DeviceTreeNode);
305
306for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next)
307{
308flatProp = (DeviceTreeNodeProperty *)buffer;
309strcpy(flatProp->name, prop->name);
310flatProp->length = prop->length;
311buffer += sizeof(DeviceTreeNodeProperty);
312bcopy(prop->value, buffer, prop->length);
313buffer += RoundToLong(prop->length);
314}
315
316flatNode->nProperties = count;
317
318for (count = 0, node = node->children; node != 0; count++, node = node->next)
319{
320buffer = FlattenNodes(node, buffer);
321}
322
323flatNode->nChildren = count;
324
325return buffer;
326}
327
328
329/*==============================================================================
330 * Flatten the in-memory representation of the device tree into a binary DT block.
331 * To get the buffer size needed, call with result = 0.
332 * To have a buffer allocated for you, call with *result = 0.
333 * To use your own buffer, call with *result = &buffer.
334 */
335
336void DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)
337{
338uint32_t totalSize;
339void * buf;
340
341DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);
342
343#if DEBUG
344if (buffer_p)
345{
346DT__PrintTree(rootNode);
347}
348#endif
349
350totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) + DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) + DTInfo.totalPropertySize;
351
352DPRINTF("Total size 0x%x\n", totalSize);
353
354if (buffer_p != 0)
355{
356if (totalSize == 0)
357{
358buf = 0;
359}
360else
361{
362if (*buffer_p == 0)
363{
364buf = malloc(totalSize);
365}
366else
367{
368buf = *buffer_p;
369}
370
371bzero(buf, totalSize);
372
373FlattenNodes(rootNode, buf);
374}
375
376*buffer_p = buf;
377}
378
379if (length)
380{
381*length = totalSize;
382}
383}
384
385
386//==============================================================================
387
388char * DT__GetName(Node *node)
389{
390Property *prop;
391
392//DPRINTF("DT__GetName(0x%x)\n", node);
393//DPRINTF("Node properties = 0x%x\n", node->properties);
394for (prop = node->properties; prop; prop = prop->next)
395{
396//DPRINTF("Prop '%s'\n", prop->name);
397if (strcmp(prop->name, "name") == 0)
398{
399return prop->value;
400}
401}
402
403//DPRINTF("DT__GetName returns 0\n");
404return "(null)";
405}
406
407
408//==============================================================================
409
410Node * DT__FindNode(const char *path, bool createIfMissing)
411{
412Node *node, *child;
413DTPropertyNameBuf nameBuf;
414char *bp;
415int i;
416
417DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
418
419// Start at root
420node = rootNode;
421
422DPRINTF("root = 0x%x\n", rootNode);
423
424while (node)
425{
426// Skip leading slash
427while (*path == '/')
428{
429path++;
430}
431
432for (i = 0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++)
433{
434*bp = *path;
435}
436
437*bp = '\0';
438
439if (nameBuf[0] == '\0')
440{
441// last path entry
442break;
443}
444
445DPRINTF("Node '%s'\n", nameBuf);
446
447for (child = node->children; child != 0; child = child->next)
448{
449DPRINTF("Child 0x%x\n", child);
450
451if (strcmp(DT__GetName(child), nameBuf) == 0)
452{
453break;
454}
455}
456
457 if (child == 0 && createIfMissing)
458{
459DPRINTF("Creating node\n");
460
461char *str = malloc(strlen(nameBuf) + 1);
462// XXX this will leak
463strcpy(str, nameBuf);
464
465child = DT__AddChild(node, str);
466}
467
468node = child;
469}
470
471return node;
472}
473
474#if DEBUG
475
476//==============================================================================
477
478void DT__PrintNode(Node *node, int level)
479{
480char spaces[10], *cp = spaces;
481Property *prop;
482
483if (level > 9)
484{
485level = 9;
486}
487
488while (level--)
489{
490*cp++ = ' ';
491}
492
493*cp = '\0';
494
495printf("%s===Node===\n", spaces);
496
497for (prop = node->properties; prop; prop = prop->next)
498{
499char c = *((char *)prop->value);
500if (prop->length < 64 && (strcmp(prop->name, "name") == 0 || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'))
501{
502printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
503}
504else
505{
506printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
507}
508}
509
510printf("%s==========\n", spaces);
511}
512
513
514//==============================================================================
515
516static void _PrintTree(Node *node, int level)
517{
518DT__PrintNode(node, level);
519
520level++;
521
522for (node = node->children; node; node = node->next)
523{
524_PrintTree(node, level);
525}
526}
527
528void DT__PrintTree(Node *node)
529{
530if (node == 0) node = rootNode;
531_PrintTree(node, 0);
532}
533
534void DT__PrintFlattenedNode(DTEntry entry, int level)
535{
536char spaces[10], *cp = spaces;
537DTPropertyIterator propIter;
538char *name;
539void *prop;
540int propSize;
541
542if (level > 9) level = 9;
543while (level--) *cp++ = ' ';
544*cp = '\0';
545
546printf("%s===Entry %p===\n", spaces, entry);
547if (kSuccess != DTCreatePropertyIterator(entry, &propIter))
548{
549printf("Couldn't create property iterator\n");
550return;
551}
552while( kSuccess == DTIterateProperties( propIter, &name))
553{
554if( kSuccess != DTGetProperty( entry, name, &prop, &propSize ))
555continue;
556printf("%s Property %s = %s\n", spaces, name, prop);
557}
558DTDisposePropertyIterator(propIter);
559
560printf("%s==========\n", spaces);
561}
562
563static void _PrintFlattenedTree(DTEntry entry, int level)
564{
565DTEntryIterator entryIter;
566
567PrintFlattenedNode(entry, level);
568
569if (kSuccess != DTCreateEntryIterator(entry, &entryIter))
570{
571printf("Couldn't create entry iterator\n");
572return;
573}
574level++;
575while (kSuccess == DTIterateEntries( entryIter, &entry ))
576{
577_PrintFlattenedTree(entry, level);
578}
579DTDisposeEntryIterator(entryIter);
580}
581
582void DT__PrintFlattenedTree(DTEntry entry)
583{
584_PrintFlattenedTree(entry, 0);
585}
586
587
588int
589main(int argc, char **argv)
590{
591DTEntrydtEntry;
592DTPropertyIteratorpropIter;
593DTEntryIteratorentryIter;
594void*prop;
595intpropSize;
596char*name;
597void*flatTree;
598uint32_tflatSize;
599
600Node *node;
601
602node = AddChild(NULL, "device-tree");
603AddProperty(node, "potato", 4, "foo");
604AddProperty(node, "chemistry", 4, "bar");
605AddProperty(node, "physics", 4, "baz");
606
607node = AddChild(node, "dev");
608AddProperty(node, "one", 4, "one");
609AddProperty(node, "two", 4, "two");
610AddProperty(node, "three", 6, "three");
611
612node = AddChild(rootNode, "foo");
613AddProperty(node, "aaa", 4, "aab");
614AddProperty(node, "bbb", 4, "bbc");
615AddProperty(node, "cccc", 6, "ccccd");
616
617node = FindNode("/this/is/a/test", 1);
618AddProperty(node, "dddd", 12, "abcdefghijk");
619
620printf("In-memory tree:\n\n");
621
622PrintTree(rootNode);
623
624FlattenDeviceTree(&flatTree, &flatSize);
625
626printf("Flat tree = %p, size %d\n", flatTree, flatSize);
627
628dtEntry = (DTEntry)flatTree;
629
630printf("\n\nPrinting flat tree\n\n");
631
632DTInit(dtEntry);
633
634PrintFlattenedTree((DTEntry)flatTree);
635#if 0
636printf("=== Entry %p ===\n", dtEntry);
637if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter))
638{
639printf("Couldn't create property iterator\n");
640return 1;
641}
642while( kSuccess == DTIterateProperties( propIter, &name))
643{
644if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
645continue;
646printf(" Property %s = %s\n", name, prop);
647 }
648DTDisposePropertyIterator(propIter);
649printf("========\n");
650
651if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter))
652{
653printf("Couldn't create entry iterator\n");
654return 1;
655}
656while (kSuccess == DTIterateEntries( entryIter, &dtEntry ))
657{
658printf("=== Entry %p ===\n", dtEntry);
659
660if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter))
661{
662printf("Couldn't create property iterator\n");
663return 1;
664}
665while( kSuccess == DTIterateProperties( propIter, &name))
666{
667if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
668continue;
669printf(" Property %s = %s\n", name, prop);
670}
671DTDisposePropertyIterator(propIter);
672printf("========\n");
673}
674DTDisposeEntryIterator(entryIter);
675#endif
676
677return 0;
678}
679
680#endif
681
682

Archive Download this file

Revision: 2037