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