Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch_Modules/i386/libsaio/device_tree.c

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

Archive Download this file

Revision: 2238