Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/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("Done [0x%x]\n", prop);
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
223void DT__Initialize(void)
224{
225DPRINTF("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");
238}
239
240//==============================================================================
241/*
242 * Free up memory used by in-memory representation of device tree.
243 */
244void DT__Finalize(void)
245{
246Node *node;
247Property *prop;
248
249DPRINTF("DT__Finalize\n");
250
251for (prop = allocedProperties; prop != NULL; prop = prop->next)
252{
253free((void *)(prop->name));
254free(prop->value);
255}
256
257allocedProperties = NULL;
258freeProperties = NULL;
259
260for (node = allocedNodes; node != NULL; node = node->next)
261{
262free((void *)node->children);
263}
264
265allocedNodes = NULL;
266freeNodes = NULL;
267rootNode = NULL;
268
269// XXX leaks any created strings
270DTInfo.numNodes = 0;
271DTInfo.numProperties = 0;
272DTInfo.totalPropertySize = 0;
273}
274
275//==============================================================================
276
277static void *FlattenNodes(Node *node, void *buffer)
278{
279Property *prop;
280DeviceTreeNode *flatNode;
281DeviceTreeNodeProperty *flatProp;
282int count;
283
284if (node == 0) {
285return buffer;
286}
287
288flatNode = (DeviceTreeNode *)buffer;
289buffer += sizeof(DeviceTreeNode);
290
291for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next)
292{
293flatProp = (DeviceTreeNodeProperty *)buffer;
294strncpy(flatProp->name, prop->name, kPropNameLength);
295flatProp->length = prop->length;
296buffer += sizeof(DeviceTreeNodeProperty);
297bcopy(prop->value, buffer, prop->length);
298buffer += RoundToLong(prop->length);
299}
300
301flatNode->nProperties = count;
302
303for (count = 0, node = node->children; node != 0; count++, node = node->next)
304{
305buffer = FlattenNodes(node, buffer);
306}
307
308flatNode->nChildren = count;
309
310return buffer;
311}
312
313
314/*==============================================================================
315 * Flatten the in-memory representation of the device tree into a binary DT block.
316 * To get the buffer size needed, call with result = 0.
317 * To have a buffer allocated for you, call with *result = 0.
318 * To use your own buffer, call with *result = &buffer.
319 */
320
321void DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)
322{
323uint32_t totalSize;
324void * buf;
325
326DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);
327
328#if DEBUG
329if (buffer_p) {
330DT__PrintTree(rootNode);
331}
332#endif
333
334totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) +
335DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) +
336DTInfo.totalPropertySize;
337
338DPRINTF("Total size 0x%x\n", totalSize);
339
340if (buffer_p != 0)
341{
342if (totalSize == 0)
343{
344buf = 0;
345}
346else
347{
348if (*buffer_p == 0)
349{
350buf = malloc(totalSize);
351}
352else
353{
354buf = *buffer_p;
355}
356if (!buf)
357{
358*length = 0;
359return;
360}
361
362bzero(buf, totalSize);
363
364FlattenNodes(rootNode, buf);
365}
366
367*buffer_p = buf;
368}
369
370if (length)
371{
372*length = totalSize;
373}
374}
375
376//==============================================================================
377
378char *DT__GetName(Node *node)
379{
380Property *prop;
381
382//DPRINTF("DT__GetName(0x%x)\n", node);
383//DPRINTF("Node properties = 0x%x\n", node->properties);
384for (prop = node->properties; prop; prop = prop->next)
385{
386//DPRINTF("Prop '%s'\n", prop->name);
387if (strncmp(prop->name, "name", sizeof("name")) == 0)
388{
389return prop->value;
390}
391}
392
393//DPRINTF("DT__GetName returns 0\n");
394return "(null)";
395}
396
397//==============================================================================
398// Bungo
399Property *DT__GetProperty(Node *node, const char *name)
400{
401Property *prop;
402
403for (prop = node->properties; prop; prop = prop->next)
404{
405if (strcmp(prop->name, name) == 0)
406{
407return prop;
408}
409}
410
411return NULL;
412}
413
414//==============================================================================
415
416Node *DT__FindNode(const char *path, bool createIfMissing)
417{
418Node *node, *child;
419DTPropertyNameBuf nameBuf;
420char *bp;
421int i;
422
423DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
424
425// Start at root
426node = rootNode;
427
428DPRINTF("DT__FindNode: root = 0x%x\n", rootNode);
429
430while (node)
431{
432// Skip leading slash(es)
433while (*path == '/')
434{
435path++;
436}
437
438for (i = 0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++)
439{
440*bp = *path;
441}
442
443*bp = '\0';
444
445if (nameBuf[0] == '\0')
446{
447// last path entry
448break;
449}
450
451DPRINTF("DT__FindNode: Node '%s'\n", nameBuf);
452
453for (child = node->children; child != 0; child = child->next)
454{
455DPRINTF("DT__FindNode: Child 0x%x\n", child);
456
457if (strcmp(DT__GetName(child), nameBuf) == 0)
458{
459break;
460}
461}
462
463if (child == 0 && createIfMissing)
464{
465char *str = malloc(strlen(nameBuf) + 1);
466// XXX this will leak
467strcpy(str, nameBuf);
468
469child = DT__AddChild(node, str);
470DPRINTF("DT__FindNode: Creating node: %s\n", str);
471}
472
473node = child;
474}
475
476return node;
477}
478
479#if DEBUG
480
481//==============================================================================
482
483void DT__PrintNode(Node *node, int level)
484{
485char spaces[10], *cp = spaces;
486Property *prop;
487
488if (level > 9)
489{
490level = 9;
491}
492
493while (level--)
494{
495*cp++ = ' ';
496}
497
498*cp = '\0';
499
500printf("%s===Node===\n", spaces);
501
502for (prop = node->properties; prop; prop = prop->next)
503{
504char c = *((char *)prop->value);
505if (prop->length < 64 && (strncmp(prop->name, "name", sizeof("name") ) == 0 || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'))
506{
507printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
508}
509else
510{
511printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
512}
513}
514
515printf("%s==========\n", spaces);
516}
517
518//==============================================================================
519
520static void _PrintTree(Node *node, int level)
521{
522DT__PrintNode(node, level);
523
524level++;
525
526for (node = node->children; node; node = node->next)
527{
528_PrintTree(node, level);
529}
530}
531
532//==============================================================================
533
534void DT__PrintTree(Node *node)
535{
536if (node == 0) node = rootNode;
537_PrintTree(node, 0);
538}
539
540//==============================================================================
541
542void DT__PrintFlattenedNode(DTEntry entry, int level)
543{
544char spaces[10], *cp = spaces;
545DTPropertyIterator propIter;
546char *name;
547void *prop;
548int propSize;
549
550if (level > 9) level = 9;
551while (level--) *cp++ = ' ';
552*cp = '\0';
553
554printf("%s===Entry %p===\n", spaces, entry);
555if (kSuccess != DTCreatePropertyIterator(entry, &propIter))
556{
557printf("Couldn't create property iterator\n");
558return;
559}
560while( kSuccess == DTIterateProperties( propIter, &name))
561{
562if( kSuccess != DTGetProperty( entry, name, &prop, &propSize ))
563continue;
564printf("%s Property %s = %s\n", spaces, name, prop);
565}
566DTDisposePropertyIterator(propIter);
567
568printf("%s==========\n", spaces);
569}
570
571//==============================================================================
572
573static void _PrintFlattenedTree(DTEntry entry, int level)
574{
575DTEntryIterator entryIter;
576
577PrintFlattenedNode(entry, level);
578
579if (kSuccess != DTCreateEntryIterator(entry, &entryIter))
580{
581printf("Couldn't create entry iterator\n");
582return;
583}
584level++;
585while (kSuccess == DTIterateEntries( entryIter, &entry ))
586{
587_PrintFlattenedTree(entry, level);
588}
589DTDisposeEntryIterator(entryIter);
590}
591
592//==============================================================================
593
594void DT__PrintFlattenedTree(DTEntry entry)
595{
596_PrintFlattenedTree(entry, 0);
597}
598
599//==============================================================================
600
601int main(int argc, char **argv)
602{
603DTEntrydtEntry;
604DTPropertyIteratorpropIter;
605DTEntryIteratorentryIter;
606void*prop;
607intpropSize;
608char*name;
609void*flatTree;
610uint32_tflatSize;
611
612Node *node;
613
614node = AddChild(NULL, "device-tree");
615AddProperty(node, "potato", 4, "foo");
616AddProperty(node, "chemistry", 4, "bar");
617AddProperty(node, "physics", 4, "baz");
618
619node = AddChild(node, "dev");
620AddProperty(node, "one", 4, "one");
621AddProperty(node, "two", 4, "two");
622AddProperty(node, "three", 6, "three");
623
624node = AddChild(rootNode, "foo");
625AddProperty(node, "aaa", 4, "aab");
626AddProperty(node, "bbb", 4, "bbc");
627AddProperty(node, "cccc", 6, "ccccd");
628
629node = FindNode("/this/is/a/test", 1);
630AddProperty(node, "dddd", 12, "abcdefghijk");
631
632printf("In-memory tree:\n\n");
633
634PrintTree(rootNode);
635
636FlattenDeviceTree(&flatTree, &flatSize);
637
638printf("Flat tree = %p, size %d\n", flatTree, flatSize);
639
640dtEntry = (DTEntry)flatTree;
641
642printf("\n\nPrinting flat tree\n\n");
643
644DTInit(dtEntry);
645
646PrintFlattenedTree((DTEntry)flatTree);
647#if 0
648printf("=== Entry %p ===\n", dtEntry);
649if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter))
650{
651printf("Couldn't create property iterator\n");
652return 1;
653}
654while( kSuccess == DTIterateProperties( propIter, &name))
655{
656if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
657continue;
658printf(" Property %s = %s\n", name, prop);
659 }
660DTDisposePropertyIterator(propIter);
661printf("========\n");
662
663if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter))
664{
665printf("Couldn't create entry iterator\n");
666return 1;
667}
668while (kSuccess == DTIterateEntries( entryIter, &dtEntry ))
669{
670printf("=== Entry %p ===\n", dtEntry);
671
672if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter))
673{
674printf("Couldn't create property iterator\n");
675return 1;
676}
677while( kSuccess == DTIterateProperties( propIter, &name))
678{
679if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
680continue;
681printf(" Property %s = %s\n", name, prop);
682}
683DTDisposePropertyIterator(propIter);
684printf("========\n");
685}
686DTDisposeEntryIterator(entryIter);
687#endif
688
689return 0;
690}
691
692#endif
693
694

Archive Download this file

Revision: 2679