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

Archive Download this file

Revision: 2531