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