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