Chameleon

Chameleon Svn Source Tree

Root/tags/2.3/i386/libsaio/device_tree.c

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

Archive Download this file

Revision: HEAD