Root/
Source at commit 1305 created 12 years 8 months ago. By meklort, Cleanup arch makefiles. Begin merging of BootX source - will need cleaning up | |
---|---|
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 | * ci.c - Functions for accessing Open Firmware's Client Interface␊ |
24 | *␊ |
25 | * Copyright (c) 1998-2002 Apple Computer, Inc.␊ |
26 | *␊ |
27 | * DRI: Josh de Cesare␊ |
28 | */␊ |
29 | ␊ |
30 | #include <sl.h>␊ |
31 | ␊ |
32 | static ClientInterfacePtr gCIPtr;␊ |
33 | ␊ |
34 | long InitCI(ClientInterfacePtr ciPtr)␊ |
35 | {␊ |
36 | gCIPtr = ciPtr;␊ |
37 | ␊ |
38 | return 0;␊ |
39 | }␊ |
40 | ␊ |
41 | long CallCI(CIArgs *ciArgsPtr)␊ |
42 | {␊ |
43 | long ret;␊ |
44 | ␊ |
45 | ret = (*gCIPtr)(ciArgsPtr);␊ |
46 | return ret;␊ |
47 | }␊ |
48 | ␊ |
49 | ␊ |
50 | // Device Tree␊ |
51 | ␊ |
52 | // Peer take a phandle and returns the next peer.␊ |
53 | // It returns zero of there are no more peers.␊ |
54 | CICell Peer(CICell phandle)␊ |
55 | {␊ |
56 | CIArgs ciArgs;␊ |
57 | CICell peer_ph;␊ |
58 | long ret;␊ |
59 | ␊ |
60 | ciArgs.service = "peer";␊ |
61 | ciArgs.nArgs = 1;␊ |
62 | ciArgs.nReturns = 1;␊ |
63 | ciArgs.args.peer.phandle = phandle;␊ |
64 | ␊ |
65 | ret = CallCI(&ciArgs);␊ |
66 | if (ret != 0) return kCIError;␊ |
67 | ␊ |
68 | peer_ph = ciArgs.args.peer.peerPhandle;␊ |
69 | ␊ |
70 | return peer_ph;␊ |
71 | }␊ |
72 | ␊ |
73 | // Child take a phandle and returns the first child.␊ |
74 | // It returns zero of there in no child.␊ |
75 | CICell Child(CICell phandle)␊ |
76 | {␊ |
77 | CIArgs ciArgs;␊ |
78 | CICell child_ph;␊ |
79 | long ret;␊ |
80 | ␊ |
81 | ciArgs.service = "child";␊ |
82 | ciArgs.nArgs = 1;␊ |
83 | ciArgs.nReturns = 1;␊ |
84 | ciArgs.args.child.phandle = phandle;␊ |
85 | ␊ |
86 | ret = CallCI(&ciArgs);␊ |
87 | if (ret != 0) return kCIError;␊ |
88 | ␊ |
89 | child_ph = ciArgs.args.child.childPhandle;␊ |
90 | ␊ |
91 | return child_ph;␊ |
92 | }␊ |
93 | ␊ |
94 | // Parent take a phandle and returns the parent node.␊ |
95 | // It returns zero of if the phandle is the root node.␊ |
96 | CICell Parent(CICell phandle)␊ |
97 | {␊ |
98 | CIArgs ciArgs;␊ |
99 | CICell parent_ph;␊ |
100 | long ret;␊ |
101 | ␊ |
102 | ciArgs.service = "parent";␊ |
103 | ciArgs.nArgs = 1;␊ |
104 | ciArgs.nReturns = 1;␊ |
105 | ciArgs.args.parent.childPhandle = phandle;␊ |
106 | ␊ |
107 | ret = CallCI(&ciArgs);␊ |
108 | if (ret != 0) return kCIError;␊ |
109 | ␊ |
110 | parent_ph = ciArgs.args.parent.parentPhandle;␊ |
111 | ␊ |
112 | return parent_ph;␊ |
113 | }␊ |
114 | ␊ |
115 | // FindDevice take a device spec and returns the phandle.␊ |
116 | // It returns zero of if the device was not found.␊ |
117 | CICell FindDevice(char *devSpec)␊ |
118 | {␊ |
119 | CIArgs ciArgs;␊ |
120 | CICell phandle;␊ |
121 | long ret;␊ |
122 | ␊ |
123 | ciArgs.service = "finddevice";␊ |
124 | ciArgs.nArgs = 1;␊ |
125 | ciArgs.nReturns = 1;␊ |
126 | ciArgs.args.finddevice.devSpec = devSpec;␊ |
127 | ␊ |
128 | ret = CallCI(&ciArgs);␊ |
129 | if (ret != 0) return kCIError;␊ |
130 | ␊ |
131 | phandle = ciArgs.args.finddevice.phandle;␊ |
132 | ␊ |
133 | return phandle;␊ |
134 | }␊ |
135 | ␊ |
136 | // InstanceToPath take an ihandle, buf and buflen. Set the device path␊ |
137 | // to the package in buf upto buflen characters and returns the length␊ |
138 | // Length will be -1 if the ihandle is invalid.␊ |
139 | CICell InstanceToPath(CICell ihandle, char *buf, long buflen)␊ |
140 | {␊ |
141 | CIArgs ciArgs;␊ |
142 | CICell length;␊ |
143 | long ret;␊ |
144 | ␊ |
145 | ciArgs.service = "instance-to-path";␊ |
146 | ciArgs.nArgs = 3;␊ |
147 | ciArgs.nReturns = 1;␊ |
148 | ciArgs.args.instanceToPath.ihandle = ihandle;␊ |
149 | ciArgs.args.instanceToPath.buf = buf;␊ |
150 | ciArgs.args.instanceToPath.buflen = buflen;␊ |
151 | ␊ |
152 | ret = CallCI(&ciArgs);␊ |
153 | if (ret != 0) return kCIError;␊ |
154 | ␊ |
155 | length = ciArgs.args.instanceToPath.length;␊ |
156 | ␊ |
157 | return length;␊ |
158 | }␊ |
159 | ␊ |
160 | // InstanceToPackage take an ihandle and returns the phandle for it.␊ |
161 | // returns -1 if the phandle can't be found.␊ |
162 | CICell InstanceToPackage(CICell ihandle)␊ |
163 | {␊ |
164 | CIArgs ciArgs;␊ |
165 | CICell phandle;␊ |
166 | long ret;␊ |
167 | ␊ |
168 | ciArgs.service = "instance-to-package";␊ |
169 | ciArgs.nArgs = 1;␊ |
170 | ciArgs.nReturns = 1;␊ |
171 | ciArgs.args.instanceToPackage.ihandle = ihandle;␊ |
172 | ␊ |
173 | ret = CallCI(&ciArgs);␊ |
174 | if (ret != 0) return kCIError;␊ |
175 | ␊ |
176 | phandle = ciArgs.args.instanceToPackage.phandle;␊ |
177 | ␊ |
178 | return phandle;␊ |
179 | }␊ |
180 | ␊ |
181 | // InstanceToPackages␊ |
182 | ␊ |
183 | // PackageToPath take a phandle, buf and buflen. Set the device path␊ |
184 | // to the package in buf upto buflen characters and returns the length␊ |
185 | // Length will be -1 if the phandle is invalid.␊ |
186 | CICell PackageToPath(CICell phandle, char *buf, long buflen)␊ |
187 | {␊ |
188 | CIArgs ciArgs;␊ |
189 | CICell length;␊ |
190 | long ret;␊ |
191 | ␊ |
192 | if (gOFVersion >= kOFVersion2x) {␊ |
193 | ciArgs.service = "package-to-path";␊ |
194 | ciArgs.nArgs = 3;␊ |
195 | ciArgs.nReturns = 1;␊ |
196 | ciArgs.args.packageToPath.phandle = phandle;␊ |
197 | ciArgs.args.packageToPath.buf = buf;␊ |
198 | ciArgs.args.packageToPath.buflen = buflen;␊ |
199 | ␊ |
200 | ret = CallCI(&ciArgs);␊ |
201 | if (ret != 0) return kCIError;␊ |
202 | ␊ |
203 | length = ciArgs.args.packageToPath.length;␊ |
204 | } else {␊ |
205 | ret = CallMethod(3, 1, SLWordsIH, "slw_pwd", phandle,␊ |
206 | ␉␉ (CICell)buf, buflen, &length);␊ |
207 | if (ret != 0) return kCIError;␊ |
208 | ␊ |
209 | buf[length] = '\0';␊ |
210 | }␊ |
211 | ␊ |
212 | return length;␊ |
213 | }␊ |
214 | ␊ |
215 | // Canon␊ |
216 | ␊ |
217 | // GetPropLen takes a phandle and prop name␊ |
218 | // and returns the size of the property␊ |
219 | // or -1 if the property is not valid.␊ |
220 | CICell GetPropLen(CICell phandle, char *name)␊ |
221 | {␊ |
222 | CIArgs ciArgs;␊ |
223 | CICell size;␊ |
224 | long ret;␊ |
225 | ␊ |
226 | ciArgs.service = "getproplen";␊ |
227 | ciArgs.nArgs = 2;␊ |
228 | ciArgs.nReturns = 1;␊ |
229 | ciArgs.args.getproplen.phandle = phandle;␊ |
230 | ciArgs.args.getproplen.name = name;␊ |
231 | ␊ |
232 | ret = CallCI(&ciArgs);␊ |
233 | if (ret != 0) return kCIError;␊ |
234 | ␊ |
235 | size = ciArgs.args.getproplen.size;␊ |
236 | ␊ |
237 | return size;␊ |
238 | }␊ |
239 | ␊ |
240 | // GetProp takes a phandle, prop name, buffer and length␊ |
241 | // and copied the property value in to the buffer.␊ |
242 | // returns -1 if the property is not valid.␊ |
243 | CICell GetProp(CICell phandle, char *name, char *buf, long buflen)␊ |
244 | {␊ |
245 | CIArgs ciArgs;␊ |
246 | CICell size;␊ |
247 | long ret;␊ |
248 | ␊ |
249 | ciArgs.service = "getprop";␊ |
250 | ciArgs.nArgs = 4;␊ |
251 | ciArgs.nReturns = 1;␊ |
252 | ciArgs.args.getprop.phandle = phandle;␊ |
253 | ciArgs.args.getprop.name = name;␊ |
254 | ciArgs.args.getprop.buf = buf;␊ |
255 | ciArgs.args.getprop.buflen = buflen;␊ |
256 | ␊ |
257 | ret = CallCI(&ciArgs);␊ |
258 | if (ret != 0) return kCIError;␊ |
259 | ␊ |
260 | size = ciArgs.args.getprop.size;␊ |
261 | ␊ |
262 | return size;␊ |
263 | }␊ |
264 | ␊ |
265 | // NextProp takes a phandle, prev name, and a buffer␊ |
266 | // and copied the next property name in to the buffer.␊ |
267 | // returns -1 if the property is not valid.␊ |
268 | // returns 0 if the prev was the last property.␊ |
269 | // returns 1 otherwise.␊ |
270 | CICell NextProp(CICell phandle, char *previous, char *buf)␊ |
271 | {␊ |
272 | CIArgs ciArgs;␊ |
273 | CICell flag;␊ |
274 | long ret;␊ |
275 | ␊ |
276 | ciArgs.service = "nextprop";␊ |
277 | ciArgs.nArgs = 3;␊ |
278 | ciArgs.nReturns = 1;␊ |
279 | ciArgs.args.nextprop.phandle = phandle;␊ |
280 | ciArgs.args.nextprop.previous = previous;␊ |
281 | ciArgs.args.nextprop.buf = buf;␊ |
282 | ␊ |
283 | ret = CallCI(&ciArgs);␊ |
284 | if (ret != 0) return kCIError;␊ |
285 | ␊ |
286 | flag = ciArgs.args.nextprop.flag;␊ |
287 | ␊ |
288 | return flag;␊ |
289 | }␊ |
290 | ␊ |
291 | // SetProp takes a phandle, prop name, buffer and length␊ |
292 | // and copied the buffer in to the property value.␊ |
293 | // returns -1 if the property could not be set or created.␊ |
294 | CICell SetProp(CICell phandle, char *name, char *buf, long buflen)␊ |
295 | {␊ |
296 | CIArgs ciArgs;␊ |
297 | CICell size;␊ |
298 | long ret;␊ |
299 | ␊ |
300 | ciArgs.service = "setprop";␊ |
301 | ciArgs.nArgs = 4;␊ |
302 | ciArgs.nReturns = 1;␊ |
303 | ciArgs.args.setprop.phandle = phandle;␊ |
304 | ciArgs.args.setprop.name = name;␊ |
305 | ciArgs.args.setprop.buf = buf;␊ |
306 | ciArgs.args.setprop.buflen = buflen;␊ |
307 | ␊ |
308 | ret = CallCI(&ciArgs);␊ |
309 | if (ret != 0) return kCIError;␊ |
310 | ␊ |
311 | size = ciArgs.args.setprop.size;␊ |
312 | ␊ |
313 | return size;␊ |
314 | }␊ |
315 | ␊ |
316 | ␊ |
317 | // Device I/O␊ |
318 | ␊ |
319 | // Open takes a device specifier and returns an iHandle␊ |
320 | // It returns zero if the device can not be found or opened.␊ |
321 | CICell Open(char *devSpec)␊ |
322 | {␊ |
323 | CIArgs ciArgs;␊ |
324 | CICell ihandle;␊ |
325 | long ret;␊ |
326 | ␊ |
327 | // intercept software RAID's virtual devices␊ |
328 | if(isRAIDPath(devSpec))␊ |
329 | return (CICell)RAIDOpen(devSpec);␊ |
330 | ␊ |
331 | ciArgs.service = "open";␊ |
332 | ciArgs.nArgs = 1;␊ |
333 | ciArgs.nReturns = 1;␊ |
334 | ciArgs.args.open.devSpec = devSpec;␊ |
335 | ␊ |
336 | ret = CallCI(&ciArgs);␊ |
337 | if (ret != 0) return 0;␊ |
338 | ␊ |
339 | ihandle = ciArgs.args.open.ihandle;␊ |
340 | ␊ |
341 | return ihandle;␊ |
342 | }␊ |
343 | ␊ |
344 | // Close takes an iHandle and closes the device.␊ |
345 | void Close(CICell ihandle)␊ |
346 | {␊ |
347 | CIArgs ciArgs;␊ |
348 | ␊ |
349 | if(isRAIDDevice((void*)ihandle)) {␊ |
350 | RAIDClose((RAIDDevicePtr)ihandle);␊ |
351 | return;␊ |
352 | }␊ |
353 | ␊ |
354 | ciArgs.service = "close";␊ |
355 | ciArgs.nArgs = 1;␊ |
356 | ciArgs.nReturns = 0;␊ |
357 | ciArgs.args.close.ihandle = ihandle;␊ |
358 | ␊ |
359 | CallCI(&ciArgs);␊ |
360 | }␊ |
361 | ␊ |
362 | // Read takes an iHandle, an address and a length and return the actual␊ |
363 | // Length read. Returns -1 if the operaction failed.␊ |
364 | CICell Read(CICell ihandle, long addr, long length)␊ |
365 | {␊ |
366 | CIArgs ciArgs;␊ |
367 | long actual;␊ |
368 | long ret;␊ |
369 | ␊ |
370 | if(isRAIDDevice((void*)ihandle))␊ |
371 | return RAIDRead((RAIDDevicePtr)ihandle, addr, length, -1);␊ |
372 | ␊ |
373 | ciArgs.service = "read";␊ |
374 | ciArgs.nArgs = 3;␊ |
375 | ciArgs.nReturns = 1;␊ |
376 | ciArgs.args.read.ihandle = ihandle;␊ |
377 | ciArgs.args.read.addr = addr;␊ |
378 | ciArgs.args.read.length = length;␊ |
379 | ␊ |
380 | ret = CallCI(&ciArgs);␊ |
381 | if (ret != 0) return kCIError;␊ |
382 | ␊ |
383 | actual = ciArgs.args.read.actual;␊ |
384 | ␊ |
385 | // Spin the wait cursor.␊ |
386 | Spin();␊ |
387 | ␊ |
388 | return actual;␊ |
389 | }␊ |
390 | ␊ |
391 | // Write takes an iHandle, an address and a length and return the actual␊ |
392 | // Length written. Returns -1 if the operaction failed.␊ |
393 | CICell Write(CICell ihandle, long addr, long length)␊ |
394 | {␊ |
395 | CIArgs ciArgs;␊ |
396 | long actual;␊ |
397 | long ret;␊ |
398 | ␊ |
399 | if(isRAIDDevice((void*)ihandle)) {␊ |
400 | printf("who's trying to write to RAID?!\n");␊ |
401 | return -1;␊ |
402 | }␊ |
403 | ␊ |
404 | ciArgs.service = "write";␊ |
405 | ciArgs.nArgs = 3;␊ |
406 | ciArgs.nReturns = 1;␊ |
407 | ciArgs.args.write.ihandle = ihandle;␊ |
408 | ciArgs.args.write.addr = addr;␊ |
409 | ciArgs.args.write.length = length;␊ |
410 | ␊ |
411 | ret = CallCI(&ciArgs);␊ |
412 | if (ret != 0) return kCIError;␊ |
413 | ␊ |
414 | actual = ciArgs.args.write.actual;␊ |
415 | ␊ |
416 | return actual;␊ |
417 | }␊ |
418 | ␊ |
419 | // Seek takes an iHandle, and a 64 bit position␊ |
420 | // and moves to that address in file.␊ |
421 | // returns seeks result, or -1 if seek is not supported.␊ |
422 | CICell Seek(CICell ihandle, long long position)␊ |
423 | {␊ |
424 | CIArgs ciArgs;␊ |
425 | long ret;␊ |
426 | ␊ |
427 | if(isRAIDDevice((void*)ihandle))␊ |
428 | return RAIDSeek((RAIDDevicePtr)ihandle, position);␊ |
429 | ␊ |
430 | ciArgs.service = "seek";␊ |
431 | ciArgs.nArgs = 3;␊ |
432 | ciArgs.nReturns = 1;␊ |
433 | ciArgs.args.seek.ihandle = ihandle;␊ |
434 | ciArgs.args.seek.pos_high = position >> 32;␊ |
435 | ciArgs.args.seek.pos_low = position & 0x00000000FFFFFFFFULL;␊ |
436 | ␊ |
437 | ret = CallCI(&ciArgs);␊ |
438 | if (ret != 0) return kCIError;␊ |
439 | ␊ |
440 | ret = ciArgs.args.seek.result;␊ |
441 | ␊ |
442 | return ret;␊ |
443 | }␊ |
444 | ␊ |
445 | ␊ |
446 | // Other Device Method Invocation␊ |
447 | ␊ |
448 | // Call the specified method on the given iHandle with the listed arguments.␊ |
449 | long CallMethod(long args, long rets, CICell iHandle, const char *method, ...)␊ |
450 | {␊ |
451 | va_list argList;␊ |
452 | CIArgs ciArgs;␊ |
453 | long ret, cnt, error = kCINoError;␊ |
454 | ␊ |
455 | va_start(argList, method);␊ |
456 | ␊ |
457 | ciArgs.service = "call-method";␊ |
458 | ciArgs.nArgs = args + 2;␊ |
459 | ciArgs.nReturns = rets + 1;␊ |
460 | ciArgs.args.callMethod.iHandle = iHandle;␊ |
461 | ciArgs.args.callMethod.method = method;␊ |
462 | ␊ |
463 | for (cnt = 0; cnt < args; cnt++) {␊ |
464 | ciArgs.args.callMethod.cells[args - cnt - 1] = va_arg(argList, CICell);␊ |
465 | }␊ |
466 | ␊ |
467 | ret = CallCI(&ciArgs);␊ |
468 | if (ret != 0) error = kCIError;␊ |
469 | else if (ciArgs.args.callMethod.cells[args] != 0) error = kCICatch;␊ |
470 | ␊ |
471 | if (error == kCINoError) {␊ |
472 | for (cnt = 0; cnt < rets; cnt++) {␊ |
473 | *(va_arg(argList, CICell *)) =␊ |
474 | ␉ciArgs.args.callMethod.cells[args + rets - cnt];␊ |
475 | }␊ |
476 | }␊ |
477 | ␊ |
478 | va_end(argList);␊ |
479 | ␊ |
480 | return error;␊ |
481 | }␊ |
482 | ␊ |
483 | ␊ |
484 | // Memory␊ |
485 | ␊ |
486 | // Claim takes a virt address, a size, and an alignment.␊ |
487 | // It return baseaddr or -1 for claim failed.␊ |
488 | CICell Claim(CICell virt, CICell size, CICell align)␊ |
489 | {␊ |
490 | CIArgs ciArgs;␊ |
491 | CICell baseaddr;␊ |
492 | long ret;␊ |
493 | ␊ |
494 | if (gOFVersion >= kOFVersion2x) {␊ |
495 | // Claim actually works, so use it.␊ |
496 | ciArgs.service = "claim";␊ |
497 | ciArgs.nArgs = 3;␊ |
498 | ciArgs.nReturns = 1;␊ |
499 | ciArgs.args.claim.virt = virt;␊ |
500 | ciArgs.args.claim.size = size;␊ |
501 | ciArgs.args.claim.align = align;␊ |
502 | ␊ |
503 | ret = CallCI(&ciArgs);␊ |
504 | if (ret != 0) return kCIError;␊ |
505 | ␊ |
506 | baseaddr = ciArgs.args.claim.baseaddr;␊ |
507 | } else {␊ |
508 | // Claim does not work. Do it by hand.␊ |
509 | if ((gMMUIH == 0) || (gMMUIH == 0)) return kCIError;␊ |
510 | ␊ |
511 | // Get the physical memory␊ |
512 | ret = CallMethod(3, 1, gMemoryIH, "claim", virt, size, 0, &baseaddr);␊ |
513 | if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;␊ |
514 | ␊ |
515 | // Get the logical memory␊ |
516 | ret = CallMethod(3, 1, gMMUIH, "claim", virt, size, 0, &baseaddr);␊ |
517 | if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;␊ |
518 | ␊ |
519 | // Map them together.␊ |
520 | ret = CallMethod(4, 0, gMMUIH, "map", virt, virt, size, 0);␊ |
521 | if (ret != kCINoError) return kCIError;␊ |
522 | }␊ |
523 | ␊ |
524 | return baseaddr;␊ |
525 | }␊ |
526 | ␊ |
527 | // Release takes a virt address, a size␊ |
528 | void Release(CICell virt, CICell size)␊ |
529 | {␊ |
530 | CIArgs ciArgs;␊ |
531 | ␊ |
532 | ciArgs.service = "release";␊ |
533 | ciArgs.nArgs = 2;␊ |
534 | ciArgs.nReturns = 0;␊ |
535 | ciArgs.args.claim.virt = virt;␊ |
536 | ciArgs.args.claim.size = size;␊ |
537 | ␊ |
538 | CallCI(&ciArgs);␊ |
539 | }␊ |
540 | ␊ |
541 | ␊ |
542 | // Control Transfer␊ |
543 | ␊ |
544 | // Boot trys to boot the bootspec␊ |
545 | void Boot(char *bootspec)␊ |
546 | {␊ |
547 | CIArgs ciArgs;␊ |
548 | ␊ |
549 | ciArgs.service = "boot";␊ |
550 | ciArgs.nArgs = 1;␊ |
551 | ciArgs.nReturns = 0;␊ |
552 | ciArgs.args.boot.bootspec = bootspec;␊ |
553 | ␊ |
554 | CallCI(&ciArgs);␊ |
555 | }␊ |
556 | ␊ |
557 | // Enter the user interface.␊ |
558 | // Executing the 'go' command returns to the client.␊ |
559 | void Enter(void)␊ |
560 | {␊ |
561 | CIArgs ciArgs;␊ |
562 | ␊ |
563 | ciArgs.service = "enter";␊ |
564 | ciArgs.nArgs = 0;␊ |
565 | ciArgs.nReturns = 0;␊ |
566 | ␊ |
567 | CallCI(&ciArgs);␊ |
568 | }␊ |
569 | ␊ |
570 | // Exit the client program.␊ |
571 | void Exit(void)␊ |
572 | {␊ |
573 | CIArgs ciArgs;␊ |
574 | ␊ |
575 | ciArgs.service = "exit";␊ |
576 | ciArgs.nArgs = 0;␊ |
577 | ciArgs.nReturns = 0;␊ |
578 | ␊ |
579 | CallCI(&ciArgs);␊ |
580 | }␊ |
581 | ␊ |
582 | // Clain␊ |
583 | ␊ |
584 | // Quiesce stops any async tasks in Open Firmware.␊ |
585 | void Quiesce(void)␊ |
586 | {␊ |
587 | CIArgs ciArgs;␊ |
588 | ␊ |
589 | ciArgs.service = "quiesce";␊ |
590 | ciArgs.nArgs = 0;␊ |
591 | ciArgs.nReturns = 0;␊ |
592 | ␊ |
593 | CallCI(&ciArgs);␊ |
594 | }␊ |
595 | ␊ |
596 | ␊ |
597 | // User Interface␊ |
598 | ␊ |
599 | // Interpret the given forth string with the listed arguments.␊ |
600 | long Interpret(long args, long rets, const char *forthString, ...)␊ |
601 | {␊ |
602 | va_list argList;␊ |
603 | CIArgs ciArgs;␊ |
604 | long ret, cnt, error = kCINoError;␊ |
605 | ␊ |
606 | va_start(argList, forthString);␊ |
607 | ␊ |
608 | ciArgs.service = "interpret";␊ |
609 | ciArgs.nArgs = args + 1;␊ |
610 | ciArgs.nReturns = rets + 1;␊ |
611 | ciArgs.args.interpret.forth = forthString;␊ |
612 | ␊ |
613 | for (cnt = 0; cnt < args; cnt++) {␊ |
614 | ciArgs.args.interpret.cells[args - cnt - 1] = va_arg(argList, CICell);␊ |
615 | }␊ |
616 | ␊ |
617 | ret = CallCI(&ciArgs);␊ |
618 | if (ret != 0) error = kCIError;␊ |
619 | else if (ciArgs.args.interpret.cells[args] != 0) error = kCICatch;␊ |
620 | ␊ |
621 | if (error == kCINoError) {␊ |
622 | for (cnt = 0; cnt < rets; cnt++) {␊ |
623 | *(va_arg(argList, CICell *)) =␊ |
624 | ␉ciArgs.args.interpret.cells[args + rets - cnt];␊ |
625 | }␊ |
626 | }␊ |
627 | ␊ |
628 | va_end(argList);␊ |
629 | ␊ |
630 | return error;␊ |
631 | }␊ |
632 |