Root/
Source at commit 284 created 13 years 10 months ago. By blackosx, Amended my mistake by updating the Default theme images in the trunk. Now put them back as they were.. (Sorry) | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2005 Apple Computer, Inc. All Rights Reserved.␊ |
3 | */␊ |
4 | ␊ |
5 | #if 1␊ |
6 | /*␊ |
7 | ␊ |
8 | Structures for a Flattened Device Tree ␊ |
9 | */␊ |
10 | ␊ |
11 | #define kPropNameLength 32␊ |
12 | ␊ |
13 | typedef struct DeviceTreeNodeProperty {␊ |
14 | char name[kPropNameLength]; // NUL terminated property name␊ |
15 | unsigned long length; // Length (bytes) of folloing prop value␊ |
16 | // unsigned long value[1]; // Variable length value of property␊ |
17 | // Padded to a multiple of a longword?␊ |
18 | } DeviceTreeNodeProperty;␊ |
19 | ␊ |
20 | typedef struct OpaqueDTEntry {␊ |
21 | unsigned long nProperties; // Number of props[] elements (0 => end)␊ |
22 | unsigned long nChildren; // Number of children[] elements␊ |
23 | // DeviceTreeNodeProperty props[];// array size == nProperties␊ |
24 | // DeviceTreeNode children[]; // array size == nChildren␊ |
25 | } DeviceTreeNode;␊ |
26 | ␊ |
27 | typedef char DTPropertyNameBuf[32];␊ |
28 | /* Entry Name Definitions (Entry Names are C-Strings)*/␊ |
29 | enum {␊ |
30 | kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */␊ |
31 | };␊ |
32 | ␊ |
33 | /* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/␊ |
34 | typedef char DTEntryNameBuf[32];␊ |
35 | #endif␊ |
36 | ␊ |
37 | #include "libsaio.h"␊ |
38 | #include "device_tree.h"␊ |
39 | ␊ |
40 | #if DEBUG␊ |
41 | #define DPRINTF(args...) printf(args)␊ |
42 | void␊ |
43 | DT__PrintTree(Node *node);␊ |
44 | #else␊ |
45 | #define DPRINTF(args...)␊ |
46 | #endif␊ |
47 | ␊ |
48 | ␊ |
49 | #define RoundToLong(x)␉(((x) + 3) & ~3)␊ |
50 | ␊ |
51 | static struct _DTSizeInfo {␊ |
52 | uint32_t numNodes;␊ |
53 | uint32_t numProperties;␊ |
54 | uint32_t totalPropertySize;␊ |
55 | } DTInfo;␊ |
56 | ␊ |
57 | #define kAllocSize 4096␊ |
58 | ␊ |
59 | static Node *rootNode;␊ |
60 | ␊ |
61 | static Node *freeNodes, *allocedNodes;␊ |
62 | static Property *freeProperties, *allocedProperties;␊ |
63 | ␊ |
64 | Property *␊ |
65 | DT__AddProperty(Node *node, const char *name, uint32_t length, void *value)␊ |
66 | {␊ |
67 | Property *prop;␊ |
68 | ␊ |
69 | DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value);␊ |
70 | if (freeProperties == NULL) {␊ |
71 | void *buf = malloc(kAllocSize);␊ |
72 | int i;␊ |
73 | ␊ |
74 | DPRINTF("Allocating more free properties\n");␊ |
75 | if (buf == 0) return 0;␊ |
76 | bzero(buf, kAllocSize);␊ |
77 | // Use the first property to record the allocated buffer␊ |
78 | // for later freeing.␊ |
79 | prop = (Property *)buf;␊ |
80 | prop->next = allocedProperties;␊ |
81 | allocedProperties = prop;␊ |
82 | prop->value = buf;␊ |
83 | prop++;␊ |
84 | for (i=1; i<(kAllocSize / sizeof(Property)); i++) {␊ |
85 | prop->next = freeProperties;␊ |
86 | freeProperties = prop;␊ |
87 | prop++;␊ |
88 | }␊ |
89 | }␊ |
90 | prop = freeProperties;␊ |
91 | freeProperties = prop->next;␊ |
92 | ␊ |
93 | prop->name = name;␊ |
94 | prop->length = length;␊ |
95 | prop->value = value;␊ |
96 | ␊ |
97 | // Always add to end of list␊ |
98 | if (node->properties == 0) {␊ |
99 | node->properties = prop;␊ |
100 | } else {␊ |
101 | node->last_prop->next = prop;␊ |
102 | }␊ |
103 | node->last_prop = prop;␊ |
104 | prop->next = 0;␊ |
105 | ␊ |
106 | DPRINTF("Done [0x%x]\n", prop);␊ |
107 | ␊ |
108 | DTInfo.numProperties++;␊ |
109 | DTInfo.totalPropertySize += RoundToLong(length);␊ |
110 | ␊ |
111 | return prop;␊ |
112 | }␊ |
113 | ␊ |
114 | Node *␊ |
115 | DT__AddChild(Node *parent, const char *name)␊ |
116 | {␊ |
117 | Node *node;␊ |
118 | ␊ |
119 | if (freeNodes == NULL) {␊ |
120 | void *buf = malloc(kAllocSize);␊ |
121 | int i;␊ |
122 | ␊ |
123 | DPRINTF("Allocating more free nodes\n");␊ |
124 | if (buf == 0) return 0;␊ |
125 | bzero(buf, kAllocSize);␊ |
126 | node = (Node *)buf;␊ |
127 | // Use the first node to record the allocated buffer␊ |
128 | // for later freeing.␊ |
129 | node->next = allocedNodes;␊ |
130 | allocedNodes = node;␊ |
131 | node->children = (Node *)buf;␊ |
132 | node++;␊ |
133 | for (i=1; i<(kAllocSize / sizeof(Node)); i++) {␊ |
134 | node->next = freeNodes;␊ |
135 | freeNodes = node;␊ |
136 | node++;␊ |
137 | }␊ |
138 | }␊ |
139 | DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name);␊ |
140 | node = freeNodes;␊ |
141 | freeNodes = node->next;␊ |
142 | DPRINTF("Got free node 0x%x\n", node);␊ |
143 | DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next);␊ |
144 | ␊ |
145 | if (parent == NULL) {␊ |
146 | rootNode = node;␊ |
147 | node->next = 0;␊ |
148 | } else {␊ |
149 | node->next = parent->children;␊ |
150 | parent->children = node;␊ |
151 | }␊ |
152 | DTInfo.numNodes++;␊ |
153 | DT__AddProperty(node, "name", strlen(name) + 1, (void *) name);␊ |
154 | return node;␊ |
155 | }␊ |
156 | ␊ |
157 | void␊ |
158 | DT__FreeProperty(Property *prop)␊ |
159 | {␊ |
160 | prop->next = freeProperties;␊ |
161 | freeProperties = prop;␊ |
162 | }␊ |
163 | void␊ |
164 | DT__FreeNode(Node *node)␊ |
165 | {␊ |
166 | node->next = freeNodes;␊ |
167 | freeNodes = node;␊ |
168 | }␊ |
169 | ␊ |
170 | void␊ |
171 | DT__Initialize(void)␊ |
172 | {␊ |
173 | DPRINTF("DT__Initialize\n");␊ |
174 | ␊ |
175 | freeNodes = 0;␊ |
176 | allocedNodes = 0;␊ |
177 | freeProperties = 0;␊ |
178 | allocedProperties = 0;␊ |
179 | ␊ |
180 | DTInfo.numNodes = 0;␊ |
181 | DTInfo.numProperties = 0;␊ |
182 | DTInfo.totalPropertySize = 0;␊ |
183 | ␊ |
184 | rootNode = DT__AddChild(NULL, "/");␊ |
185 | DPRINTF("DT__Initialize done\n");␊ |
186 | }␊ |
187 | ␊ |
188 | /*␊ |
189 | * Free up memory used by in-memory representation␊ |
190 | * of device tree.␊ |
191 | */␊ |
192 | void␊ |
193 | DT__Finalize(void)␊ |
194 | {␊ |
195 | Node *node;␊ |
196 | Property *prop;␊ |
197 | ␊ |
198 | DPRINTF("DT__Finalize\n");␊ |
199 | for (prop = allocedProperties; prop != NULL; prop = prop->next) {␊ |
200 | free(prop->value);␊ |
201 | }␊ |
202 | allocedProperties = NULL;␊ |
203 | freeProperties = NULL;␊ |
204 | ␊ |
205 | for (node = allocedNodes; node != NULL; node = node->next) {␊ |
206 | free((void *)node->children);␊ |
207 | }␊ |
208 | allocedNodes = NULL;␊ |
209 | freeNodes = NULL;␊ |
210 | rootNode = NULL;␊ |
211 | ␊ |
212 | // XXX leaks any created strings␊ |
213 | ␊ |
214 | DTInfo.numNodes = 0;␊ |
215 | DTInfo.numProperties = 0;␊ |
216 | DTInfo.totalPropertySize = 0;␊ |
217 | }␊ |
218 | ␊ |
219 | static void *␊ |
220 | FlattenNodes(Node *node, void *buffer)␊ |
221 | {␊ |
222 | Property *prop;␊ |
223 | DeviceTreeNode *flatNode;␊ |
224 | DeviceTreeNodeProperty *flatProp;␊ |
225 | int count;␊ |
226 | ␊ |
227 | if (node == 0) return buffer;␊ |
228 | ␊ |
229 | flatNode = (DeviceTreeNode *)buffer;␊ |
230 | buffer += sizeof(DeviceTreeNode);␊ |
231 | ␊ |
232 | for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next) {␊ |
233 | flatProp = (DeviceTreeNodeProperty *)buffer;␊ |
234 | strcpy(flatProp->name, prop->name);␊ |
235 | flatProp->length = prop->length;␊ |
236 | buffer += sizeof(DeviceTreeNodeProperty);␊ |
237 | bcopy(prop->value, buffer, prop->length);␊ |
238 | buffer += RoundToLong(prop->length);␊ |
239 | }␊ |
240 | flatNode->nProperties = count;␊ |
241 | ␊ |
242 | for (count = 0, node = node->children; node != 0; count++, node = node->next) {␊ |
243 | buffer = FlattenNodes(node, buffer);␊ |
244 | }␊ |
245 | flatNode->nChildren = count;␊ |
246 | ␊ |
247 | return buffer;␊ |
248 | }␊ |
249 | ␊ |
250 | /*␊ |
251 | * Flatten the in-memory representation of the device tree␊ |
252 | * into a binary DT block.␊ |
253 | * To get the buffer size needed, call with result = 0.␊ |
254 | * To have a buffer allocated for you, call with *result = 0.␊ |
255 | * To use your own buffer, call with *result = &buffer.␊ |
256 | */␊ |
257 | ␊ |
258 | void␊ |
259 | DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)␊ |
260 | {␊ |
261 | uint32_t totalSize;␊ |
262 | void *buf;␊ |
263 | ␊ |
264 | DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);␊ |
265 | #if DEBUG␊ |
266 | if (buffer_p) DT__PrintTree(rootNode);␊ |
267 | #endif␊ |
268 | ␊ |
269 | totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) + ␊ |
270 | DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) +␊ |
271 | DTInfo.totalPropertySize;␊ |
272 | ␊ |
273 | DPRINTF("Total size 0x%x\n", totalSize);␊ |
274 | if (buffer_p != 0) {␊ |
275 | if (totalSize == 0) {␊ |
276 | buf = 0;␊ |
277 | } else {␊ |
278 | if (*buffer_p == 0) {␊ |
279 | buf = malloc(totalSize);␊ |
280 | } else {␊ |
281 | buf = *buffer_p;␊ |
282 | }␊ |
283 | bzero(buf, totalSize);␊ |
284 | ␊ |
285 | FlattenNodes(rootNode, buf);␊ |
286 | }␊ |
287 | *buffer_p = buf;␊ |
288 | }␊ |
289 | if (length)␊ |
290 | *length = totalSize;␊ |
291 | }␊ |
292 | ␊ |
293 | char *␊ |
294 | DT__GetName(Node *node)␊ |
295 | {␊ |
296 | Property *prop;␊ |
297 | ␊ |
298 | //DPRINTF("DT__GetName(0x%x)\n", node);␊ |
299 | //DPRINTF("Node properties = 0x%x\n", node->properties);␊ |
300 | for (prop = node->properties; prop; prop = prop->next) {␊ |
301 | //DPRINTF("Prop '%s'\n", prop->name);␊ |
302 | if (strcmp(prop->name, "name") == 0) {␊ |
303 | return prop->value;␊ |
304 | }␊ |
305 | }␊ |
306 | //DPRINTF("DT__GetName returns 0\n");␊ |
307 | return "(null)";␊ |
308 | }␊ |
309 | ␊ |
310 | Node *␊ |
311 | DT__FindNode(const char *path, bool createIfMissing)␊ |
312 | {␊ |
313 | Node *node, *child;␊ |
314 | DTPropertyNameBuf nameBuf;␊ |
315 | char *bp;␊ |
316 | int i;␊ |
317 | ␊ |
318 | DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);␊ |
319 | ␊ |
320 | // Start at root␊ |
321 | node = rootNode;␊ |
322 | DPRINTF("root = 0x%x\n", rootNode);␊ |
323 | ␊ |
324 | while (node) {␊ |
325 | // Skip leading slash␊ |
326 | while (*path == '/') path++;␊ |
327 | ␊ |
328 | for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path;␊ |
329 | *bp = '\0';␊ |
330 | ␊ |
331 | if (nameBuf[0] == '\0') {␊ |
332 | // last path entry␊ |
333 | break;␊ |
334 | }␊ |
335 | DPRINTF("Node '%s'\n", nameBuf);␊ |
336 | ␊ |
337 | for (child = node->children; child != 0; child = child->next) {␊ |
338 | DPRINTF("Child 0x%x\n", child);␊ |
339 | if (strcmp(DT__GetName(child), nameBuf) == 0) {␊ |
340 | break;␊ |
341 | }␊ |
342 | }␊ |
343 | if (child == 0 && createIfMissing) {␊ |
344 | DPRINTF("Creating node\n");␊ |
345 | char *str = malloc(strlen(nameBuf) + 1);␊ |
346 | // XXX this will leak␊ |
347 | strcpy(str, nameBuf);␊ |
348 | ␊ |
349 | child = DT__AddChild(node, str);␊ |
350 | }␊ |
351 | node = child;␊ |
352 | }␊ |
353 | return node;␊ |
354 | }␊ |
355 | ␊ |
356 | #if DEBUG␊ |
357 | ␊ |
358 | void␊ |
359 | DT__PrintNode(Node *node, int level)␊ |
360 | {␊ |
361 | char spaces[10], *cp = spaces;␊ |
362 | Property *prop;␊ |
363 | ␊ |
364 | if (level > 9) level = 9;␊ |
365 | while (level--) *cp++ = ' ';␊ |
366 | *cp = '\0';␊ |
367 | ␊ |
368 | printf("%s===Node===\n", spaces);␊ |
369 | for (prop = node->properties; prop; prop = prop->next) {␊ |
370 | char c = *((char *)prop->value);␊ |
371 | if (prop->length < 64 && (␊ |
372 | strcmp(prop->name, "name") == 0 || ␊ |
373 | (c >= '0' && c <= '9') ||␊ |
374 | (c >= 'a' && c <= 'z') ||␊ |
375 | (c >= 'A' && c <= 'Z') || c == '_')) {␊ |
376 | printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);␊ |
377 | } else {␊ |
378 | printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);␊ |
379 | }␊ |
380 | }␊ |
381 | printf("%s==========\n", spaces);␊ |
382 | }␊ |
383 | ␊ |
384 | static void␊ |
385 | _PrintTree(Node *node, int level)␊ |
386 | {␊ |
387 | DT__PrintNode(node, level);␊ |
388 | level++;␊ |
389 | for (node = node->children; node; node = node->next)␊ |
390 | _PrintTree(node, level);␊ |
391 | }␊ |
392 | ␊ |
393 | void␊ |
394 | DT__PrintTree(Node *node)␊ |
395 | {␊ |
396 | if (node == 0) node = rootNode;␊ |
397 | _PrintTree(node, 0);␊ |
398 | }␊ |
399 | ␊ |
400 | void␊ |
401 | DT__PrintFlattenedNode(DTEntry entry, int level)␊ |
402 | {␊ |
403 | char spaces[10], *cp = spaces;␊ |
404 | DTPropertyIterator␉ propIter;␊ |
405 | char *name;␊ |
406 | void *prop;␊ |
407 | int propSize;␊ |
408 | ␊ |
409 | if (level > 9) level = 9;␊ |
410 | while (level--) *cp++ = ' ';␊ |
411 | *cp = '\0';␊ |
412 | ␊ |
413 | printf("%s===Entry %p===\n", spaces, entry);␊ |
414 | if (kSuccess != DTCreatePropertyIterator(entry, &propIter)) {␊ |
415 | printf("Couldn't create property iterator\n");␊ |
416 | return;␊ |
417 | }␊ |
418 | while( kSuccess == DTIterateProperties( propIter, &name)) {␊ |
419 | if( kSuccess != DTGetProperty( entry, name, &prop, &propSize ))␊ |
420 | continue;␊ |
421 | printf("%s Property %s = %s\n", spaces, name, prop);␊ |
422 | }␊ |
423 | DTDisposePropertyIterator(propIter);␊ |
424 | ␊ |
425 | printf("%s==========\n", spaces);␊ |
426 | }␊ |
427 | ␊ |
428 | static void␊ |
429 | _PrintFlattenedTree(DTEntry entry, int level)␊ |
430 | {␊ |
431 | DTEntryIterator entryIter;␊ |
432 | ␊ |
433 | PrintFlattenedNode(entry, level);␊ |
434 | ␊ |
435 | if (kSuccess != DTCreateEntryIterator(entry, &entryIter)) {␊ |
436 | printf("Couldn't create entry iterator\n");␊ |
437 | return;␊ |
438 | }␊ |
439 | level++;␊ |
440 | while (kSuccess == DTIterateEntries( entryIter, &entry )) {␊ |
441 | _PrintFlattenedTree(entry, level);␊ |
442 | }␊ |
443 | DTDisposeEntryIterator(entryIter);␊ |
444 | }␊ |
445 | ␊ |
446 | void␊ |
447 | DT__PrintFlattenedTree(DTEntry entry)␊ |
448 | {␊ |
449 | _PrintFlattenedTree(entry, 0);␊ |
450 | }␊ |
451 | ␊ |
452 | ␊ |
453 | int␊ |
454 | main(int argc, char **argv)␊ |
455 | {␊ |
456 | DTEntry dtEntry;␊ |
457 | DTPropertyIterator␉ propIter;␊ |
458 | DTEntryIterator entryIter;␊ |
459 | void␉␉␉␉*prop;␊ |
460 | int␉␉␉␉␉propSize;␊ |
461 | char␉␉␉␉*name;␊ |
462 | void *flatTree;␊ |
463 | uint32_t flatSize;␊ |
464 | ␊ |
465 | Node *node;␊ |
466 | ␊ |
467 | node = AddChild(NULL, "device-tree");␊ |
468 | AddProperty(node, "potato", 4, "foo");␊ |
469 | AddProperty(node, "chemistry", 4, "bar");␊ |
470 | AddProperty(node, "physics", 4, "baz");␊ |
471 | ␊ |
472 | node = AddChild(node, "dev");␊ |
473 | AddProperty(node, "one", 4, "one");␊ |
474 | AddProperty(node, "two", 4, "two");␊ |
475 | AddProperty(node, "three", 6, "three");␊ |
476 | ␊ |
477 | node = AddChild(rootNode, "foo");␊ |
478 | AddProperty(node, "aaa", 4, "aab");␊ |
479 | AddProperty(node, "bbb", 4, "bbc");␊ |
480 | AddProperty(node, "cccc", 6, "ccccd");␊ |
481 | ␊ |
482 | node = FindNode("/this/is/a/test", 1);␊ |
483 | AddProperty(node, "dddd", 12, "abcdefghijk");␊ |
484 | ␊ |
485 | printf("In-memory tree:\n\n");␊ |
486 | ␊ |
487 | PrintTree(rootNode);␊ |
488 | ␊ |
489 | FlattenDeviceTree(&flatTree, &flatSize);␊ |
490 | ␊ |
491 | printf("Flat tree = %p, size %d\n", flatTree, flatSize);␊ |
492 | ␊ |
493 | dtEntry = (DTEntry)flatTree;␊ |
494 | ␊ |
495 | printf("\n\nPrinting flat tree\n\n");␊ |
496 | ␊ |
497 | DTInit(dtEntry);␊ |
498 | ␊ |
499 | PrintFlattenedTree((DTEntry)flatTree);␊ |
500 | #if 0␊ |
501 | printf("=== Entry %p ===\n", dtEntry);␊ |
502 | if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {␊ |
503 | printf("Couldn't create property iterator\n");␊ |
504 | return 1;␊ |
505 | }␊ |
506 | while( kSuccess == DTIterateProperties( propIter, &name)) {␊ |
507 | if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))␊ |
508 | continue;␊ |
509 | printf(" Property %s = %s\n", name, prop);␊ |
510 | }␊ |
511 | DTDisposePropertyIterator(propIter);␊ |
512 | printf("========\n");␊ |
513 | ␊ |
514 | if (kSuccess != DTCreateEntryIterator(dtEntry, &entryIter)) {␊ |
515 | printf("Couldn't create entry iterator\n");␊ |
516 | return 1;␊ |
517 | }␊ |
518 | while (kSuccess == DTIterateEntries( entryIter, &dtEntry )) {␊ |
519 | printf("=== Entry %p ===\n", dtEntry);␊ |
520 | ␊ |
521 | if (kSuccess != DTCreatePropertyIterator(dtEntry, &propIter)) {␊ |
522 | printf("Couldn't create property iterator\n");␊ |
523 | return 1;␊ |
524 | }␊ |
525 | while( kSuccess == DTIterateProperties( propIter, &name)) {␊ |
526 | if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))␊ |
527 | continue;␊ |
528 | printf(" Property %s = %s\n", name, prop);␊ |
529 | }␊ |
530 | DTDisposePropertyIterator(propIter);␊ |
531 | printf("========\n");␊ |
532 | }␊ |
533 | DTDisposeEntryIterator(entryIter);␊ |
534 | #endif␊ |
535 | ␊ |
536 | return 0;␊ |
537 | }␊ |
538 | ␊ |
539 | #endif␊ |
540 | ␊ |
541 |