]> git.saurik.com Git - apple/xnu.git/blame - pexpert/gen/device_tree.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / pexpert / gen / device_tree.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 */
31
32#include <pexpert/protos.h>
33#include <pexpert/boot.h>
34#include <pexpert/device_tree.h>
91447636
A
35
36#include <mach/mach_types.h>
1c79356b 37#include <mach/machine/vm_types.h>
91447636
A
38#include <kern/kern_types.h>
39#include <kern/kalloc.h>
40
1c79356b 41#include <sys/types.h>
1c79356b
A
42
43#ifndef NULL
44#define NULL ((void *) 0)
45#endif
46
47#define round_long(x) (((x) + 3) & -4)
48#define next_prop(x) ((DeviceTreeNodeProperty *) (((int)x) + sizeof(DeviceTreeNodeProperty) + round_long(x->length)))
49
50/* Entry*/
51typedef DeviceTreeNode *RealDTEntry;
52
53typedef struct DTSavedScope {
54 struct DTSavedScope * nextScope;
55 RealDTEntry scope;
56 RealDTEntry entry;
57 unsigned long index;
58} *DTSavedScopePtr;
59
60/* Entry Iterator*/
61typedef struct OpaqueDTEntryIterator {
62 RealDTEntry outerScope;
63 RealDTEntry currentScope;
64 RealDTEntry currentEntry;
65 DTSavedScopePtr savedScope;
66 unsigned long currentIndex;
67} *RealDTEntryIterator;
68
69/* Property Iterator*/
70typedef struct OpaqueDTPropertyIterator {
71 RealDTEntry entry;
72 DeviceTreeNodeProperty *currentProperty;
73 unsigned long currentIndex;
74} *RealDTPropertyIterator;
75
76static int DTInitialized;
77static RealDTEntry DTRootNode;
78
1c79356b
A
79/*
80 * Support Routines
81 */
82static RealDTEntry
83skipProperties(RealDTEntry entry)
84{
85 DeviceTreeNodeProperty *prop;
2d21ac55 86 unsigned int k;
1c79356b
A
87
88 if (entry == NULL || entry->nProperties == 0) {
89 return NULL;
90 } else {
91 prop = (DeviceTreeNodeProperty *) (entry + 1);
92 for (k = 0; k < entry->nProperties; k++) {
93 prop = next_prop(prop);
94 }
95 }
96 return ((RealDTEntry) prop);
97}
98
99static RealDTEntry
100skipTree(RealDTEntry root)
101{
102 RealDTEntry entry;
2d21ac55 103 unsigned int k;
1c79356b
A
104
105 entry = skipProperties(root);
106 if (entry == NULL) {
107 return NULL;
108 }
109 for (k = 0; k < root->nChildren; k++) {
110 entry = skipTree(entry);
111 }
112 return entry;
113}
114
115static RealDTEntry
116GetFirstChild(RealDTEntry parent)
117{
118 return skipProperties(parent);
119}
120
121static RealDTEntry
122GetNextChild(RealDTEntry sibling)
123{
124 return skipTree(sibling);
125}
126
127static const char *
128GetNextComponent(const char *cp, char *bp)
129{
130 while (*cp != 0) {
131 if (*cp == kDTPathNameSeparator) {
132 cp++;
133 break;
134 }
135 *bp++ = *cp++;
136 }
137 *bp = 0;
138 return cp;
139}
140
141static RealDTEntry
142FindChild(RealDTEntry cur, char *buf)
143{
144 RealDTEntry child;
145 unsigned long index;
2d21ac55
A
146 char * str;
147 unsigned int dummy;
1c79356b
A
148
149 if (cur->nChildren == 0) {
150 return NULL;
151 }
152 index = 1;
153 child = GetFirstChild(cur);
154 while (1) {
155 if (DTGetProperty(child, "name", (void **)&str, &dummy) != kSuccess) {
156 break;
157 }
158 if (strcmp(str, buf) == 0) {
159 return child;
160 }
161 if (index >= cur->nChildren) {
162 break;
163 }
164 child = GetNextChild(child);
165 index++;
166 }
167 return NULL;
168}
169
170
171/*
172 * External Routines
173 */
174void
175DTInit(void *base)
176{
177 DTRootNode = (RealDTEntry) base;
178 DTInitialized = (DTRootNode != 0);
179}
180
181int
182DTEntryIsEqual(const DTEntry ref1, const DTEntry ref2)
183{
184 /* equality of pointers */
185 return (ref1 == ref2);
186}
187
188static char *startingP; // needed for find_entry
189int find_entry(const char *propName, const char *propValue, DTEntry *entryH);
190
191int DTFindEntry(const char *propName, const char *propValue, DTEntry *entryH)
192{
193 if (!DTInitialized) {
194 return kError;
195 }
196
197 startingP = (char *)DTRootNode;
198 return(find_entry(propName, propValue, entryH));
199}
200
201int find_entry(const char *propName, const char *propValue, DTEntry *entryH)
202{
203 DeviceTreeNode *nodeP = (DeviceTreeNode *) startingP;
2d21ac55 204 unsigned int k;
1c79356b
A
205
206 if (nodeP->nProperties == 0) return(kError); // End of the list of nodes
207 startingP = (char *) (nodeP + 1);
208
209 // Search current entry
210 for (k = 0; k < nodeP->nProperties; ++k) {
211 DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) startingP;
212
213 startingP += sizeof (*propP) + ((propP->length + 3) & -4);
214
215 if (strcmp (propP->name, propName) == 0) {
2d21ac55 216 if (propValue == NULL || strcmp( (char *)(propP + 1), propValue) == 0)
1c79356b
A
217 {
218 *entryH = (DTEntry)nodeP;
219 return(kSuccess);
220 }
221 }
222 }
223
224 // Search child nodes
225 for (k = 0; k < nodeP->nChildren; ++k)
226 {
227 if (find_entry(propName, propValue, entryH) == kSuccess)
228 return(kSuccess);
229 }
230 return(kError);
231}
232
233int
234DTLookupEntry(const DTEntry searchPoint, const char *pathName, DTEntry *foundEntry)
235{
236 DTEntryNameBuf buf;
237 RealDTEntry cur;
238 const char * cp;
239
240 if (!DTInitialized) {
241 return kError;
242 }
243 if (searchPoint == NULL) {
244 cur = DTRootNode;
245 } else {
246 cur = searchPoint;
247 }
248 cp = pathName;
249 if (*cp == kDTPathNameSeparator) {
250 cp++;
251 if (*cp == 0) {
252 *foundEntry = cur;
253 return kSuccess;
254 }
255 }
256 do {
257 cp = GetNextComponent(cp, buf);
258
259 /* Check for done */
260 if (*buf == 0) {
261 if (*cp == 0) {
262 *foundEntry = cur;
263 return kSuccess;
264 }
265 break;
266 }
267
268 cur = FindChild(cur, buf);
269
270 } while (cur != NULL);
271
272 return kError;
273}
274
275int
276DTCreateEntryIterator(const DTEntry startEntry, DTEntryIterator *iterator)
277{
278 RealDTEntryIterator iter;
279
280 if (!DTInitialized) {
281 return kError;
282 }
283
284 iter = (RealDTEntryIterator) kalloc(sizeof(struct OpaqueDTEntryIterator));
285 if (startEntry != NULL) {
286 iter->outerScope = (RealDTEntry) startEntry;
287 iter->currentScope = (RealDTEntry) startEntry;
288 } else {
289 iter->outerScope = DTRootNode;
290 iter->currentScope = DTRootNode;
291 }
292 iter->currentEntry = NULL;
293 iter->savedScope = NULL;
294 iter->currentIndex = 0;
295
296 *iterator = iter;
297 return kSuccess;
298}
299
300int
301DTDisposeEntryIterator(DTEntryIterator iterator)
302{
303 RealDTEntryIterator iter = iterator;
304 DTSavedScopePtr scope;
305
306 while ((scope = iter->savedScope) != NULL) {
307 iter->savedScope = scope->nextScope;
91447636 308 kfree(scope, sizeof(struct DTSavedScope));
1c79356b 309 }
91447636 310 kfree(iterator, sizeof(struct OpaqueDTEntryIterator));
1c79356b
A
311 return kSuccess;
312}
313
314int
315DTEnterEntry(DTEntryIterator iterator, DTEntry childEntry)
316{
317 RealDTEntryIterator iter = iterator;
318 DTSavedScopePtr newScope;
319
320 if (childEntry == NULL) {
321 return kError;
322 }
323 newScope = (DTSavedScopePtr) kalloc(sizeof(struct DTSavedScope));
324 newScope->nextScope = iter->savedScope;
325 newScope->scope = iter->currentScope;
326 newScope->entry = iter->currentEntry;
327 newScope->index = iter->currentIndex;
328
329 iter->currentScope = childEntry;
330 iter->currentEntry = NULL;
331 iter->savedScope = newScope;
332 iter->currentIndex = 0;
333
334 return kSuccess;
335}
336
337int
338DTExitEntry(DTEntryIterator iterator, DTEntry *currentPosition)
339{
340 RealDTEntryIterator iter = iterator;
341 DTSavedScopePtr newScope;
342
343 newScope = iter->savedScope;
344 if (newScope == NULL) {
345 return kError;
346 }
347 iter->savedScope = newScope->nextScope;
348 iter->currentScope = newScope->scope;
349 iter->currentEntry = newScope->entry;
350 iter->currentIndex = newScope->index;
351 *currentPosition = iter->currentEntry;
352
91447636 353 kfree(newScope, sizeof(struct DTSavedScope));
1c79356b
A
354
355 return kSuccess;
356}
357
358int
359DTIterateEntries(DTEntryIterator iterator, DTEntry *nextEntry)
360{
361 RealDTEntryIterator iter = iterator;
362
363 if (iter->currentIndex >= iter->currentScope->nChildren) {
364 *nextEntry = NULL;
365 return kIterationDone;
366 } else {
367 iter->currentIndex++;
368 if (iter->currentIndex == 1) {
369 iter->currentEntry = GetFirstChild(iter->currentScope);
370 } else {
371 iter->currentEntry = GetNextChild(iter->currentEntry);
372 }
373 *nextEntry = iter->currentEntry;
374 return kSuccess;
375 }
376}
377
378int
379DTRestartEntryIteration(DTEntryIterator iterator)
380{
381 RealDTEntryIterator iter = iterator;
382#if 0
383 // This commented out code allows a second argument (outer)
384 // which (if true) causes restarting at the outer scope
385 // rather than the current scope.
386 DTSavedScopePtr scope;
387
388 if (outer) {
389 while ((scope = iter->savedScope) != NULL) {
390 iter->savedScope = scope->nextScope;
391 kfree((vm_offset_t) scope, sizeof(struct DTSavedScope));
392 }
393 iter->currentScope = iter->outerScope;
394 }
395#endif
396 iter->currentEntry = NULL;
397 iter->currentIndex = 0;
398 return kSuccess;
399}
400
401int
2d21ac55 402DTGetProperty(const DTEntry entry, const char *propertyName, void **propertyValue, unsigned int *propertySize)
1c79356b
A
403{
404 DeviceTreeNodeProperty *prop;
2d21ac55 405 unsigned int k;
1c79356b
A
406
407 if (entry == NULL || entry->nProperties == 0) {
408 return kError;
409 } else {
410 prop = (DeviceTreeNodeProperty *) (entry + 1);
411 for (k = 0; k < entry->nProperties; k++) {
412 if (strcmp(prop->name, propertyName) == 0) {
413 *propertyValue = (void *) (((int)prop)
414 + sizeof(DeviceTreeNodeProperty));
415 *propertySize = prop->length;
416 return kSuccess;
417 }
418 prop = next_prop(prop);
419 }
420 }
421 return kError;
422}
423
424int
425DTCreatePropertyIterator(const DTEntry entry, DTPropertyIterator *iterator)
426{
427 RealDTPropertyIterator iter;
428
429 iter = (RealDTPropertyIterator) kalloc(sizeof(struct OpaqueDTPropertyIterator));
430 iter->entry = entry;
431 iter->currentProperty = NULL;
432 iter->currentIndex = 0;
433
434 *iterator = iter;
435 return kSuccess;
436}
437
438int
439DTDisposePropertyIterator(DTPropertyIterator iterator)
440{
91447636 441 kfree(iterator, sizeof(struct OpaqueDTPropertyIterator));
1c79356b
A
442 return kSuccess;
443}
444
445int
446DTIterateProperties(DTPropertyIterator iterator, char **foundProperty)
447{
448 RealDTPropertyIterator iter = iterator;
449
450 if (iter->currentIndex >= iter->entry->nProperties) {
451 *foundProperty = NULL;
452 return kIterationDone;
453 } else {
454 iter->currentIndex++;
455 if (iter->currentIndex == 1) {
456 iter->currentProperty = (DeviceTreeNodeProperty *) (iter->entry + 1);
457 } else {
458 iter->currentProperty = next_prop(iter->currentProperty);
459 }
460 *foundProperty = iter->currentProperty->name;
461 return kSuccess;
462 }
463}
464
465int
466DTRestartPropertyIteration(DTPropertyIterator iterator)
467{
468 RealDTPropertyIterator iter = iterator;
469
470 iter->currentProperty = NULL;
471 iter->currentIndex = 0;
472 return kSuccess;
473}
474