Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/device_tree.c

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
13typedef 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
20typedef 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
27typedef char DTPropertyNameBuf[32];
28/* Entry Name Definitions (Entry Names are C-Strings)*/
29enum {
30 kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */
31};
32
33/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
34typedef 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)
42void
43DT__PrintTree(Node *node);
44#else
45#define DPRINTF(args...)
46#endif
47
48
49#define RoundToLong(x)(((x) + 3) & ~3)
50
51static struct _DTSizeInfo {
52 uint32_t numNodes;
53 uint32_t numProperties;
54 uint32_t totalPropertySize;
55} DTInfo;
56
57#define kAllocSize 4096
58
59static Node *rootNode;
60
61static Node *freeNodes, *allocedNodes;
62static Property *freeProperties, *allocedProperties;
63
64static void *
65FlattenNodes(Node *node, void *buffer);
66#if DEBUG
67static void
68_PrintTree(Node *node, int level);
69
70#endif
71
72Property *
73DT__AddProperty(Node *node, const char *name, uint32_t length, void *value)
74{
75 Property *prop;
76
77 DPRINTF("DT__AddProperty([Node '%s'], '%s', %d, 0x%x)\n", DT__GetName(node), name, length, value);
78 if (freeProperties == NULL) {
79 void *buf = malloc(kAllocSize);
80 int i;
81
82 DPRINTF("Allocating more free properties\n");
83 if (buf == 0) return 0;
84 bzero(buf, kAllocSize);
85 // Use the first property to record the allocated buffer
86 // for later freeing.
87 prop = (Property *)buf;
88 prop->next = allocedProperties;
89 allocedProperties = prop;
90 prop->value = buf;
91 prop++;
92 for (i=1; (unsigned)i<(kAllocSize / sizeof(Property)); i++) {
93 prop->next = freeProperties;
94 freeProperties = prop;
95 prop++;
96 }
97 }
98 prop = freeProperties;
99 freeProperties = prop->next;
100
101 prop->name = name;
102 prop->length = length;
103 prop->value = value;
104
105 // Always add to end of list
106 if (node->properties == 0) {
107 node->properties = prop;
108 } else {
109 node->last_prop->next = prop;
110 }
111 node->last_prop = prop;
112 prop->next = 0;
113
114 DPRINTF("Done [0x%x]\n", prop);
115
116 DTInfo.numProperties++;
117 DTInfo.totalPropertySize += RoundToLong(length);
118
119 return prop;
120}
121
122Node *
123DT__AddChild(Node *parent, const char *name)
124{
125 Node *node;
126
127 if (freeNodes == NULL) {
128 void *buf = malloc(kAllocSize);
129 int i;
130
131 DPRINTF("Allocating more free nodes\n");
132 if (buf == 0) return 0;
133 bzero(buf, kAllocSize);
134 node = (Node *)buf;
135 // Use the first node to record the allocated buffer
136 // for later freeing.
137 node->next = allocedNodes;
138 allocedNodes = node;
139 node->children = (Node *)buf;
140 node++;
141 for (i=1; (unsigned)i<(kAllocSize / sizeof(Node)); i++) {
142 node->next = freeNodes;
143 freeNodes = node;
144 node++;
145 }
146 }
147 DPRINTF("DT__AddChild(0x%x, '%s')\n", parent, name);
148 node = freeNodes;
149 freeNodes = node->next;
150 DPRINTF("Got free node 0x%x\n", node);
151 DPRINTF("prop = 0x%x, children = 0x%x, next = 0x%x\n", node->properties, node->children, node->next);
152
153 if (parent == NULL) {
154 rootNode = node;
155 node->next = 0;
156 } else {
157 node->next = parent->children;
158 parent->children = node;
159 }
160 DTInfo.numNodes++;
161 DT__AddProperty(node, "name", strlen(name) + 1, (void *) name);
162 return node;
163}
164
165void
166DT__FreeProperty(Property *prop)
167{
168 prop->next = freeProperties;
169 freeProperties = prop;
170}
171void
172DT__FreeNode(Node *node)
173{
174 node->next = freeNodes;
175 freeNodes = node;
176}
177
178void
179DT__Initialize(void)
180{
181 DPRINTF("DT__Initialize\n");
182
183 freeNodes = 0;
184 allocedNodes = 0;
185 freeProperties = 0;
186 allocedProperties = 0;
187
188 DTInfo.numNodes = 0;
189 DTInfo.numProperties = 0;
190 DTInfo.totalPropertySize = 0;
191
192 rootNode = DT__AddChild(NULL, "/");
193 DPRINTF("DT__Initialize done\n");
194}
195
196/*
197 * Free up memory used by in-memory representation
198 * of device tree.
199 */
200void
201DT__Finalize(void)
202{
203 Node *node;
204 Property *prop;
205
206 DPRINTF("DT__Finalize\n");
207 for (prop = allocedProperties; prop != NULL; prop = prop->next) {
208 free(prop->value);
209 }
210 allocedProperties = NULL;
211 freeProperties = NULL;
212
213 for (node = allocedNodes; node != NULL; node = node->next) {
214 free((void *)node->children);
215 }
216 allocedNodes = NULL;
217 freeNodes = NULL;
218 rootNode = NULL;
219
220 // XXX leaks any created strings
221
222 DTInfo.numNodes = 0;
223 DTInfo.numProperties = 0;
224 DTInfo.totalPropertySize = 0;
225}
226
227static void *
228FlattenNodes(Node *node, void *buffer)
229{
230 Property *prop;
231 DeviceTreeNode *flatNode;
232 DeviceTreeNodeProperty *flatProp;
233 int count;
234
235 if (node == 0) return buffer;
236
237 flatNode = (DeviceTreeNode *)buffer;
238 buffer += sizeof(DeviceTreeNode);
239
240 for (count = 0, prop = node->properties; prop != 0; count++, prop = prop->next) {
241 flatProp = (DeviceTreeNodeProperty *)buffer;
242 strcpy(flatProp->name, prop->name);
243 flatProp->length = prop->length;
244 buffer += sizeof(DeviceTreeNodeProperty);
245 bcopy(prop->value, buffer, prop->length);
246 buffer += RoundToLong(prop->length);
247 }
248 flatNode->nProperties = count;
249
250 for (count = 0, node = node->children; node != 0; count++, node = node->next) {
251 buffer = FlattenNodes(node, buffer);
252 }
253 flatNode->nChildren = count;
254
255 return buffer;
256}
257
258/*
259 * Flatten the in-memory representation of the device tree
260 * into a binary DT block.
261 * To get the buffer size needed, call with result = 0.
262 * To have a buffer allocated for you, call with *result = 0.
263 * To use your own buffer, call with *result = &buffer.
264 */
265
266void
267DT__FlattenDeviceTree(void **buffer_p, uint32_t *length)
268{
269 uint32_t totalSize;
270 void *buf;
271
272 DPRINTF("DT__FlattenDeviceTree(0x%x, 0x%x)\n", buffer_p, length);
273#if DEBUG
274 if (buffer_p) DT__PrintTree(rootNode);
275#endif
276
277 totalSize = DTInfo.numNodes * sizeof(DeviceTreeNode) +
278 DTInfo.numProperties * sizeof(DeviceTreeNodeProperty) +
279 DTInfo.totalPropertySize;
280
281 DPRINTF("Total size 0x%x\n", totalSize);
282 if (buffer_p != 0) {
283 if (totalSize == 0) {
284 buf = 0;
285 } else {
286 if (*buffer_p == 0) {
287 buf = malloc(totalSize);
288 } else {
289 buf = *buffer_p;
290 }
291 bzero(buf, totalSize);
292
293 FlattenNodes(rootNode, buf);
294 }
295 *buffer_p = buf;
296 }
297 if (length)
298 *length = totalSize;
299}
300
301char *
302DT__GetName(Node *node)
303{
304 Property *prop;
305
306 //DPRINTF("DT__GetName(0x%x)\n", node);
307 //DPRINTF("Node properties = 0x%x\n", node->properties);
308 for (prop = node->properties; prop; prop = prop->next) {
309 //DPRINTF("Prop '%s'\n", prop->name);
310 if (strcmp(prop->name, "name") == 0) {
311 return prop->value;
312 }
313 }
314 //DPRINTF("DT__GetName returns 0\n");
315 return "(null)";
316}
317
318Node *
319DT__FindNode(const char *path, bool createIfMissing)
320{
321 Node *node, *child;
322 DTPropertyNameBuf nameBuf;
323 char *bp;
324 int i;
325
326 DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
327
328 // Start at root
329 node = rootNode;
330 DPRINTF("root = 0x%x\n", rootNode);
331
332 while (node) {
333 // Skip leading slash
334 while (*path == '/') path++;
335
336 for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path;
337 *bp = '\0';
338
339 if (nameBuf[0] == '\0') {
340 // last path entry
341 break;
342 }
343 DPRINTF("Node '%s'\n", nameBuf);
344
345 for (child = node->children; child != 0; child = child->next) {
346 DPRINTF("Child 0x%x\n", child);
347 if (strcmp(DT__GetName(child), nameBuf) == 0) {
348 break;
349 }
350 }
351 if (child == 0 && createIfMissing) {
352 DPRINTF("Creating node\n");
353 char *str = malloc(strlen(nameBuf) + 1);
354 // XXX this will leak
355 strcpy(str, nameBuf);
356
357 child = DT__AddChild(node, str);
358 }
359 node = child;
360 }
361 return node;
362}
363
364#if DEBUG
365
366static void
367DT__PrintNode(Node *node, int level)
368{
369 char spaces[10], *cp = spaces;
370 Property *prop;
371
372 if (level > 9) level = 9;
373 while (level--) *cp++ = ' ';
374 *cp = '\0';
375
376 printf("%s===Node===\n", spaces);
377 for (prop = node->properties; prop; prop = prop->next) {
378 char c = *((char *)prop->value);
379 if (prop->length < 64 && (
380 strcmp(prop->name, "name") == 0 ||
381 (c >= '0' && c <= '9') ||
382 (c >= 'a' && c <= 'z') ||
383 (c >= 'A' && c <= 'Z') || c == '_')) {
384 printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
385 } else {
386 printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
387 }
388 }
389 printf("%s==========\n", spaces);
390}
391
392static void
393_PrintTree(Node *node, int level)
394{
395 DT__PrintNode(node, level);
396 level++;
397 for (node = node->children; node; node = node->next)
398 _PrintTree(node, level);
399}
400
401void
402DT__PrintTree(Node *node)
403{
404 if (node == 0) node = rootNode;
405 _PrintTree(node, 0);
406}
407
408#endif
409
410

Archive Download this file

Revision: 1899