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

Archive Download this file

Revision: 2841