]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/sl.subproj/device_tree.c
BootX-34.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 *
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 * device_tree.c - Functions for flattening the Device Tree.
24 *
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30#include <sl.h>
31#include <device_tree.h>
32
33
34static long FlatenNode(CICell ph, long nodeAddr, long *nodeSize);
35static long FlatenProps(CICell ph, long propAddr, long *propSize,
36 long *numProps);
37
38// Public Functions
39
40long FlattenDeviceTree(void)
41{
42 CICell RootPH;
43 long ret;
44
45 gDeviceTreeAddr = AllocateKernelMemory(0);
46
47 RootPH = Peer(0);
48 if (RootPH == kCIError) return -1;
49
50 ret = FlatenNode(RootPH, gDeviceTreeAddr, &gDeviceTreeSize);
51
52 AllocateKernelMemory(gDeviceTreeSize);
53
54 return ret;
55}
56
57
58CICell SearchForNode(CICell ph, long top, char *prop, char *value)
59{
60 CICell curChild, result;
61
62 if (ph == 0) ph = Peer(0);
63
64 if (top == 0) {
65 // Look for it in the current node.
66 if (GetProp(ph, prop, gTempStr, 4095) != -1) {
67 if (strcmp(value, gTempStr) == 0) {
68 return ph;
69 }
70 }
71 }
72
73 // Look for it in the children.
74 curChild = Child(ph);
75
76 while (curChild != 0) {
77 result = SearchForNode(curChild, 0, prop, value);
78 if (result != 0) return result;
79 curChild = Peer(curChild);
80 }
81
82 if (top != 0) {
83 while (ph != 0) {
84 curChild = Peer(ph);
85 while (curChild != 0) {
86 result = SearchForNode(curChild, 0, prop, value);
87 if (result != 0) return result;
88 curChild = Peer(curChild);
89 }
90
91 ph = Parent(ph);
92 }
93 }
94
95 return 0;
96}
97
98
99CICell SearchForNodeMatching(CICell ph, long top, char *value)
100{
101 CICell curChild, result;
102
103 if (ph == 0) ph = Peer(0);
104
105 if (top == 0) {
106 // Look for it in the current node.
107 if (MatchThis(ph, value) == 0) return ph;
108 }
109
110 // Look for it in the children.
111 curChild = Child(ph);
112
113 while (curChild != 0) {
114 result = SearchForNodeMatching(curChild, 0, value);
115 if (result != 0) return result;
116 curChild = Peer(curChild);
117 }
118
119 if (top != 0) {
120 while (ph != 0) {
121 curChild = Peer(ph);
122 while (curChild != 0) {
123 result = SearchForNodeMatching(curChild, 0, value);
124 if (result != 0) return result;
125 curChild = Peer(curChild);
126 }
127
128 ph = Parent(ph);
129 }
130 }
131
132 return 0;
133}
134
135// Private Functions
136
137long FlatenNode(CICell ph, long nodeAddr, long *nodeSize)
138{
139 DTNodePtr node;
140 CICell childPH;
141 long curAddr, ret;
142 long propSize, numProps, childSize, numChildren;
143
144 node = (DTNodePtr)nodeAddr;
145 curAddr = nodeAddr + sizeof(DTNode);
146 numProps = 0;
147 numChildren = 0;
148
149 ret = FlatenProps(ph, curAddr, &propSize, &numProps);
150 if (ret != 0) return ret;
151
152 curAddr += propSize;
153 node->nProperties = numProps;
154
155 childPH = Child(ph);
156 if (childPH == kCIError) return -1;
157
158 while (childPH != 0) {
159 ret = FlatenNode(childPH, curAddr, &childSize);
160 curAddr += childSize;
161 numChildren++;
162
163 childPH = Peer(childPH);
164 if (childPH == -1) return -1;
165 }
166
167 node->nChildren = numChildren;
168 *nodeSize = curAddr - nodeAddr;
169
170 return 0;
171}
172
173
174long FlatenProps(CICell ph, long propAddr, long *propSize, long *numProps)
175{
176 DTPropertyPtr prop;
177 long ret, cnt, curAddr, valueAddr, valueSize, nProps;
178 char *prevName;
179
180 curAddr = propAddr;
181 prevName = "";
182 nProps = 0;
183
184 // make the first property the phandle
185 prop = (DTPropertyPtr)curAddr;
186 valueAddr = curAddr + sizeof(DTProperty);
187 strcpy(prop->name, "AAPL,phandle");
188 *((long *)valueAddr) = ph;
189 prop->length = 4;
190 curAddr = valueAddr + 4;
191 nProps++;
192
193 // Make the AAPL,unit-string property.
194 ret = PackageToPath(ph, gTempStr, 4095);
195 if (ret > 0) {
196 cnt = ret - 1;
197 while (cnt && (gTempStr[cnt - 1] != '@') &&
198 (gTempStr[cnt - 1] != '/')) cnt--;
199
200 if (gTempStr[cnt - 1] == '@') {
201 prop = (DTPropertyPtr)curAddr;
202 valueAddr = curAddr + sizeof(DTProperty);
203 strcpy(prop->name, "AAPL,unit-string");
204 strcpy((char *)valueAddr, &gTempStr[cnt]);
205 prop->length = ret - cnt;
206 curAddr = valueAddr + ((prop->length + 3) & ~3);
207 nProps++;
208 }
209 }
210
211 while (1) {
212 prop = (DTPropertyPtr)curAddr;
213 valueAddr = curAddr + sizeof(DTProperty);
214
215 ret = NextProp(ph, prevName, prop->name);
216 if (ret == -1) return -1;
217 if (ret == 0) break;
218
219 valueSize = GetProp(ph, prop->name, (char *)valueAddr,
220 kPropValueMaxLength);
221 if (valueSize == -1) return -1;
222 prop->length = valueSize;
223
224 // Save the address of the value if this is
225 // the memory map property for the device tree.
226 if ((ph == gMemoryMapPH) && !strcmp(prop->name, "DeviceTree")) {
227 gDeviceTreeMMTmp = (long *)valueAddr;
228 }
229
230 nProps++;
231 curAddr = valueAddr + ((valueSize + 3) & ~3);
232 prevName = prop->name;
233 };
234
235 *numProps = nProps;
236 *propSize = curAddr - propAddr;
237
238 return 0;
239}