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