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