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