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#include "libsaio.h"
6#include "device_tree.h"
7
8//#if 1
9/*
10
11 Structures for a Flattened Device Tree
12 */
13
14#define kPropNameLength 32
15
16typedef struct DeviceTreeNodeProperty {
17 char name[kPropNameLength]; // NUL terminated property name
18 unsigned long length; // Length (bytes) of folloing prop value
19 // unsigned long value[1]; // Variable length value of property
20 // Padded to a multiple of a longword?
21} DeviceTreeNodeProperty;
22
23typedef struct OpaqueDTEntry {
24 unsigned long nProperties; // Number of props[] elements (0 => end)
25 unsigned long nChildren; // Number of children[] elements
26 // DeviceTreeNodeProperty props[];// array size == nProperties
27 // DeviceTreeNode children[]; // array size == nChildren
28} DeviceTreeNode;
29
30typedef char DTPropertyNameBuf[32];
31/* Entry Name Definitions (Entry Names are C-Strings)*/
32enum {
33 kDTMaxEntryNameLength = 31 /* Max length of a C-String Entry Name (terminator not included) */
34};
35
36/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
37typedef char DTEntryNameBuf[32];
38//#endif
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, %p)\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 = newString(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 [%p]\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(%p, '%s')\n", parent, name);
146 node = freeNodes;
147 freeNodes = node->next;
148 DPRINTF("Got free node %p\n", node);
149 DPRINTF("prop = %p, children = %p, next = %p\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 if (prop->value) free(prop->value);
207 if (prop->name) free(prop->name);
208
209 }
210 allocedProperties = NULL;
211 freeProperties = NULL;
212
213 for (node = allocedNodes; node != NULL; node = node->next) {
214 if (node->children) 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 strlcpy(flatProp->name, prop->name, kPropNameLength);
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(%p, %u)\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 if (!buf) {
292 *length = 0;
293 return;
294 }
295 bzero(buf, totalSize);
296
297 FlattenNodes(rootNode, buf);
298 }
299 *buffer_p = buf;
300 }
301 if (length)
302 *length = totalSize;
303}
304
305char *
306DT__GetName(Node *node)
307{
308 Property *prop;
309
310 //DPRINTF("DT__GetName(0x%x)\n", node);
311 //DPRINTF("Node properties = 0x%x\n", node->properties);
312 for (prop = node->properties; prop; prop = prop->next) {
313 //DPRINTF("Prop '%s'\n", prop->name);
314 if (strncmp(prop->name, "name",sizeof("name")) == 0) {
315 return prop->value;
316 }
317 }
318 //DPRINTF("DT__GetName returns 0\n");
319 return "(null)";
320}
321
322Node *
323DT__FindNode(const char *path, bool createIfMissing)
324{
325 Node *node, *child = 0;
326 DTPropertyNameBuf nameBuf;
327 char *bp;
328 int i;
329
330 DPRINTF("DT__FindNode('%s', %d)\n", path, createIfMissing);
331
332 // Start at root
333 node = rootNode;
334 DPRINTF("root = %p\n", rootNode);
335
336 while (node) {
337 // Skip leading slash
338 while (*path == '/') path++;
339
340 for (i=0, bp = nameBuf; ++i < kDTMaxEntryNameLength && *path && *path != '/'; bp++, path++) *bp = *path;
341 *bp = '\0';
342
343 if (nameBuf[0] == '\0') {
344 // last path entry
345 break;
346 }
347 DPRINTF("Node '%s'\n", nameBuf);
348
349 for (child = node->children; child != 0; child = child->next) {
350 DPRINTF("Child %p\n", child);
351 if (strcmp(DT__GetName(child), nameBuf) == 0) {
352 break;
353 }
354 }
355 if (child == 0 && createIfMissing) {
356 DPRINTF("Creating node\n");
357
358 const char *str = newString(nameBuf);
359 if (str) {
360 child = DT__AddChild(node, str);
361 }
362 }
363 node = child;
364 }
365 return node;
366}
367
368#if DEBUG
369
370static void
371DT__PrintNode(Node *node, int level)
372{
373 char spaces[10], *cp = spaces;
374 Property *prop;
375
376 if (level > 9) level = 9;
377 while (level--) *cp++ = ' ';
378 *cp = '\0';
379
380 printf("%s===Node===\n", spaces);
381 for (prop = node->properties; prop; prop = prop->next) {
382 char c = *((char *)prop->value);
383 if (prop->length < 64 && (
384 strncmp(prop->name, "name",sizeof("name") ) == 0 ||
385 (c >= '0' && c <= '9') ||
386 (c >= 'a' && c <= 'z') ||
387 (c >= 'A' && c <= 'Z') || c == '_')) {
388 printf("%s Property '%s' [%d] = '%s'\n", spaces, prop->name, prop->length, prop->value);
389 } else {
390 printf("%s Property '%s' [%d] = (data)\n", spaces, prop->name, prop->length);
391 }
392 }
393 printf("%s==========\n", spaces);
394}
395
396static void
397_PrintTree(Node *node, int level)
398{
399 DT__PrintNode(node, level);
400 level++;
401 for (node = node->children; node; node = node->next)
402 _PrintTree(node, level);
403}
404
405void
406DT__PrintTree(Node *node)
407{
408 if (node == 0) node = rootNode;
409 _PrintTree(node, 0);
410}
411
412#endif
413
414

Archive Download this file

Revision: HEAD