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

Archive Download this file

Revision: 1929