]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/sl.subproj/device_tree.c
BootX-59.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / device_tree.c
CommitLineData
04fee52e
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
db839b1d 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
04fee52e 7 *
db839b1d
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
04fee52e
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
db839b1d
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
04fee52e
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * device_tree.c - Functions for flattening the Device Tree.
27 *
28 * Copyright (c) 1998-2000 Apple Computer, Inc.
29 *
30 * DRI: Josh de Cesare
31 */
32
33#include <sl.h>
34#include <device_tree.h>
35
36
37static long FlatenNode(CICell ph, long nodeAddr, long *nodeSize);
38static long FlatenProps(CICell ph, long propAddr, long *propSize,
39 long *numProps);
40
41// Public Functions
42
43long FlattenDeviceTree(void)
44{
45 CICell RootPH;
46 long ret;
47
48 gDeviceTreeAddr = AllocateKernelMemory(0);
49
50 RootPH = Peer(0);
51 if (RootPH == kCIError) return -1;
52
53 ret = FlatenNode(RootPH, gDeviceTreeAddr, &gDeviceTreeSize);
54
55 AllocateKernelMemory(gDeviceTreeSize);
56
57 return ret;
58}
59
60
61CICell SearchForNode(CICell ph, long top, char *prop, char *value)
62{
63 CICell curChild, result;
64
65 if (ph == 0) ph = Peer(0);
66
67 if (top == 0) {
68 // Look for it in the current node.
69 if (GetProp(ph, prop, gTempStr, 4095) != -1) {
70 if (strcmp(value, gTempStr) == 0) {
71 return ph;
72 }
73 }
74 }
75
76 // Look for it in the children.
77 curChild = Child(ph);
78
79 while (curChild != 0) {
80 result = SearchForNode(curChild, 0, prop, value);
81 if (result != 0) return result;
82 curChild = Peer(curChild);
83 }
84
85 if (top != 0) {
86 while (ph != 0) {
87 curChild = Peer(ph);
88 while (curChild != 0) {
89 result = SearchForNode(curChild, 0, prop, value);
90 if (result != 0) return result;
91 curChild = Peer(curChild);
92 }
93
94 ph = Parent(ph);
95 }
96 }
97
98 return 0;
99}
100
101
102CICell SearchForNodeMatching(CICell ph, long top, char *value)
103{
104 CICell curChild, result;
105
106 if (ph == 0) ph = Peer(0);
107
108 if (top == 0) {
109 // Look for it in the current node.
110 if (MatchThis(ph, value) == 0) return ph;
111 }
112
113 // Look for it in the children.
114 curChild = Child(ph);
115
116 while (curChild != 0) {
117 result = SearchForNodeMatching(curChild, 0, value);
118 if (result != 0) return result;
119 curChild = Peer(curChild);
120 }
121
122 if (top != 0) {
123 while (ph != 0) {
124 curChild = Peer(ph);
125 while (curChild != 0) {
126 result = SearchForNodeMatching(curChild, 0, value);
127 if (result != 0) return result;
128 curChild = Peer(curChild);
129 }
130
131 ph = Parent(ph);
132 }
133 }
134
135 return 0;
136}
137
138// Private Functions
139
140long FlatenNode(CICell ph, long nodeAddr, long *nodeSize)
141{
142 DTNodePtr node;
143 CICell childPH;
144 long curAddr, ret;
145 long propSize, numProps, childSize, numChildren;
146
147 node = (DTNodePtr)nodeAddr;
148 curAddr = nodeAddr + sizeof(DTNode);
149 numProps = 0;
150 numChildren = 0;
151
152 ret = FlatenProps(ph, curAddr, &propSize, &numProps);
153 if (ret != 0) return ret;
154
155 curAddr += propSize;
156 node->nProperties = numProps;
157
158 childPH = Child(ph);
159 if (childPH == kCIError) return -1;
160
161 while (childPH != 0) {
162 ret = FlatenNode(childPH, curAddr, &childSize);
163 curAddr += childSize;
164 numChildren++;
165
166 childPH = Peer(childPH);
167 if (childPH == -1) return -1;
168 }
169
170 node->nChildren = numChildren;
171 *nodeSize = curAddr - nodeAddr;
172
173 return 0;
174}
175
176
177long FlatenProps(CICell ph, long propAddr, long *propSize, long *numProps)
178{
179 DTPropertyPtr prop;
180 long ret, cnt, curAddr, valueAddr, valueSize, nProps;
181 char *prevName;
182
183 curAddr = propAddr;
184 prevName = "";
185 nProps = 0;
186
187 // make the first property the phandle
188 prop = (DTPropertyPtr)curAddr;
189 valueAddr = curAddr + sizeof(DTProperty);
190 strcpy(prop->name, "AAPL,phandle");
191 *((long *)valueAddr) = ph;
192 prop->length = 4;
193 curAddr = valueAddr + 4;
194 nProps++;
195
196 // Make the AAPL,unit-string property.
197 ret = PackageToPath(ph, gTempStr, 4095);
198 if (ret > 0) {
199 cnt = ret - 1;
200 while (cnt && (gTempStr[cnt - 1] != '@') &&
201 (gTempStr[cnt - 1] != '/')) cnt--;
202
203 if (gTempStr[cnt - 1] == '@') {
204 prop = (DTPropertyPtr)curAddr;
205 valueAddr = curAddr + sizeof(DTProperty);
206 strcpy(prop->name, "AAPL,unit-string");
207 strcpy((char *)valueAddr, &gTempStr[cnt]);
208 prop->length = ret - cnt;
209 curAddr = valueAddr + ((prop->length + 3) & ~3);
210 nProps++;
211 }
212 }
213
214 while (1) {
215 prop = (DTPropertyPtr)curAddr;
216 valueAddr = curAddr + sizeof(DTProperty);
217
218 ret = NextProp(ph, prevName, prop->name);
219 if (ret == -1) return -1;
220 if (ret == 0) break;
221
222 valueSize = GetProp(ph, prop->name, (char *)valueAddr,
223 kPropValueMaxLength);
224 if (valueSize == -1) return -1;
225 prop->length = valueSize;
226
227 // Save the address of the value if this is
228 // the memory map property for the device tree.
229 if ((ph == gMemoryMapPH) && !strcmp(prop->name, "DeviceTree")) {
230 gDeviceTreeMMTmp = (long *)valueAddr;
231 }
232
233 nProps++;
234 curAddr = valueAddr + ((valueSize + 3) & ~3);
235 prevName = prop->name;
236 };
237
238 *numProps = nProps;
239 *propSize = curAddr - propAddr;
240
241 return 0;
242}