Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/arch/ppc/boot2/ci.c

Source at commit 1406 created 12 years 10 months ago.
By meklort, Revert drivers.c so that kexts are only loaded when OSBundleRequired is set and that value is not safe mode. Added some comments about it too.
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
32static ClientInterfacePtr gCIPtr;
33
34long InitCI(ClientInterfacePtr ciPtr)
35{
36 gCIPtr = ciPtr;
37
38 return 0;
39}
40
41long 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.
54CICell 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.
75CICell 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.
96CICell 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.
117CICell 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.
139CICell 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.
162CICell 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.
186CICell 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.
220CICell 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.
243CICell 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.
270CICell 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.
294CICell 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.
321CICell Open(char *devSpec)
322{
323 CIArgs ciArgs;
324 CICell ihandle;
325 long ret;
326
327 ciArgs.service = "open";
328 ciArgs.nArgs = 1;
329 ciArgs.nReturns = 1;
330 ciArgs.args.open.devSpec = devSpec;
331
332 ret = CallCI(&ciArgs);
333 if (ret != 0) return 0;
334
335 ihandle = ciArgs.args.open.ihandle;
336
337 return ihandle;
338}
339
340// Close takes an iHandle and closes the device.
341void Close(CICell ihandle)
342{
343 CIArgs ciArgs;
344
345 ciArgs.service = "close";
346 ciArgs.nArgs = 1;
347 ciArgs.nReturns = 0;
348 ciArgs.args.close.ihandle = ihandle;
349
350 CallCI(&ciArgs);
351}
352
353// Read takes an iHandle, an address and a length and return the actual
354// Length read. Returns -1 if the operaction failed.
355CICell Read(CICell ihandle, long addr, long length)
356{
357 CIArgs ciArgs;
358 long actual;
359 long ret;
360
361 ciArgs.service = "read";
362 ciArgs.nArgs = 3;
363 ciArgs.nReturns = 1;
364 ciArgs.args.read.ihandle = ihandle;
365 ciArgs.args.read.addr = addr;
366 ciArgs.args.read.length = length;
367
368 ret = CallCI(&ciArgs);
369 if (ret != 0) return kCIError;
370
371 actual = ciArgs.args.read.actual;
372
373 // Spin the wait cursor.
374 Spin();
375
376 return actual;
377}
378
379// Write takes an iHandle, an address and a length and return the actual
380// Length written. Returns -1 if the operaction failed.
381CICell Write(CICell ihandle, long addr, long length)
382{
383 CIArgs ciArgs;
384 long actual;
385 long ret;
386
387 ciArgs.service = "write";
388 ciArgs.nArgs = 3;
389 ciArgs.nReturns = 1;
390 ciArgs.args.write.ihandle = ihandle;
391 ciArgs.args.write.addr = addr;
392 ciArgs.args.write.length = length;
393
394 ret = CallCI(&ciArgs);
395 if (ret != 0) return kCIError;
396
397 actual = ciArgs.args.write.actual;
398
399 return actual;
400}
401
402// Seek takes an iHandle, and a 64 bit position
403// and moves to that address in file.
404// returns seeks result, or -1 if seek is not supported.
405CICell Seek(CICell ihandle, long long position)
406{
407 CIArgs ciArgs;
408 long ret;
409
410 ciArgs.service = "seek";
411 ciArgs.nArgs = 3;
412 ciArgs.nReturns = 1;
413 ciArgs.args.seek.ihandle = ihandle;
414 ciArgs.args.seek.pos_high = position >> 32;
415 ciArgs.args.seek.pos_low = position & 0x00000000FFFFFFFFULL;
416
417 ret = CallCI(&ciArgs);
418 if (ret != 0) return kCIError;
419
420 ret = ciArgs.args.seek.result;
421
422 return ret;
423}
424
425
426// Other Device Method Invocation
427
428// Call the specified method on the given iHandle with the listed arguments.
429long CallMethod(long args, long rets, CICell iHandle, const char *method, ...)
430{
431 va_list argList;
432 CIArgs ciArgs;
433 long ret, cnt, error = kCINoError;
434
435 va_start(argList, method);
436
437 ciArgs.service = "call-method";
438 ciArgs.nArgs = args + 2;
439 ciArgs.nReturns = rets + 1;
440 ciArgs.args.callMethod.iHandle = iHandle;
441 ciArgs.args.callMethod.method = method;
442
443 for (cnt = 0; cnt < args; cnt++) {
444 ciArgs.args.callMethod.cells[args - cnt - 1] = va_arg(argList, CICell);
445 }
446
447 ret = CallCI(&ciArgs);
448 if (ret != 0) error = kCIError;
449 else if (ciArgs.args.callMethod.cells[args] != 0) error = kCICatch;
450
451 if (error == kCINoError) {
452 for (cnt = 0; cnt < rets; cnt++) {
453 *(va_arg(argList, CICell *)) =
454ciArgs.args.callMethod.cells[args + rets - cnt];
455 }
456 }
457
458 va_end(argList);
459
460 return error;
461}
462
463
464// Memory
465
466// Claim takes a virt address, a size, and an alignment.
467// It return baseaddr or -1 for claim failed.
468CICell Claim(CICell virt, CICell size, CICell align)
469{
470 CIArgs ciArgs;
471 CICell baseaddr;
472 long ret;
473
474 if (gOFVersion >= kOFVersion2x) {
475 // Claim actually works, so use it.
476 ciArgs.service = "claim";
477 ciArgs.nArgs = 3;
478 ciArgs.nReturns = 1;
479 ciArgs.args.claim.virt = virt;
480 ciArgs.args.claim.size = size;
481 ciArgs.args.claim.align = align;
482
483 ret = CallCI(&ciArgs);
484 if (ret != 0) return kCIError;
485
486 baseaddr = ciArgs.args.claim.baseaddr;
487 } else {
488 // Claim does not work. Do it by hand.
489 if ((gMMUIH == 0) || (gMMUIH == 0)) return kCIError;
490
491 // Get the physical memory
492 ret = CallMethod(3, 1, gMemoryIH, "claim", virt, size, 0, &baseaddr);
493 if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;
494
495 // Get the logical memory
496 ret = CallMethod(3, 1, gMMUIH, "claim", virt, size, 0, &baseaddr);
497 if ((ret != kCINoError) || (virt != baseaddr)) return kCIError;
498
499 // Map them together.
500 ret = CallMethod(4, 0, gMMUIH, "map", virt, virt, size, 0);
501 if (ret != kCINoError) return kCIError;
502 }
503
504 return baseaddr;
505}
506
507// Release takes a virt address, a size
508void Release(CICell virt, CICell size)
509{
510 CIArgs ciArgs;
511
512 ciArgs.service = "release";
513 ciArgs.nArgs = 2;
514 ciArgs.nReturns = 0;
515 ciArgs.args.claim.virt = virt;
516 ciArgs.args.claim.size = size;
517
518 CallCI(&ciArgs);
519}
520
521
522// Control Transfer
523
524// Boot trys to boot the bootspec
525void Boot(char *bootspec)
526{
527 CIArgs ciArgs;
528
529 ciArgs.service = "boot";
530 ciArgs.nArgs = 1;
531 ciArgs.nReturns = 0;
532 ciArgs.args.boot.bootspec = bootspec;
533
534 CallCI(&ciArgs);
535}
536
537// Enter the user interface.
538// Executing the 'go' command returns to the client.
539void Enter(void)
540{
541 CIArgs ciArgs;
542
543 ciArgs.service = "enter";
544 ciArgs.nArgs = 0;
545 ciArgs.nReturns = 0;
546
547 CallCI(&ciArgs);
548}
549
550// Exit the client program.
551void Exit(void)
552{
553 CIArgs ciArgs;
554
555 ciArgs.service = "exit";
556 ciArgs.nArgs = 0;
557 ciArgs.nReturns = 0;
558
559 CallCI(&ciArgs);
560}
561
562// Clain
563
564// Quiesce stops any async tasks in Open Firmware.
565void Quiesce(void)
566{
567 CIArgs ciArgs;
568
569 ciArgs.service = "quiesce";
570 ciArgs.nArgs = 0;
571 ciArgs.nReturns = 0;
572
573 CallCI(&ciArgs);
574}
575
576
577// User Interface
578
579// Interpret the given forth string with the listed arguments.
580long Interpret(long args, long rets, const char *forthString, ...)
581{
582 va_list argList;
583 CIArgs ciArgs;
584 long ret, cnt, error = kCINoError;
585
586 va_start(argList, forthString);
587
588 ciArgs.service = "interpret";
589 ciArgs.nArgs = args + 1;
590 ciArgs.nReturns = rets + 1;
591 ciArgs.args.interpret.forth = forthString;
592
593 for (cnt = 0; cnt < args; cnt++) {
594 ciArgs.args.interpret.cells[args - cnt - 1] = va_arg(argList, CICell);
595 }
596
597 ret = CallCI(&ciArgs);
598 if (ret != 0) error = kCIError;
599 else if (ciArgs.args.interpret.cells[args] != 0) error = kCICatch;
600
601 if (error == kCINoError) {
602 for (cnt = 0; cnt < rets; cnt++) {
603 *(va_arg(argList, CICell *)) =
604ciArgs.args.interpret.cells[args + rets - cnt];
605 }
606 }
607
608 va_end(argList);
609
610 return error;
611}
612

Archive Download this file

Revision: 1406