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