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