Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2537