|
|
1.1 root 1: /*
2: * Creation Date: <2003/11/25 14:29:08 samuel>
3: * Time-stamp: <2004/03/27 01:13:53 samuel>
4: *
5: * <client.c>
6: *
7: * OpenFirmware client interface
8: *
9: * Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
10: *
11: * This program is free software; you can redistribute it and/or
12: * modify it under the terms of the GNU General Public License
13: * version 2
14: *
15: */
16:
17: #include "config.h"
18: #include "libopenbios/bindings.h"
19: #include "libopenbios/of.h"
20:
21: /* Uncomment to enable debug printout of client interface calls */
22: //#define DEBUG_CIF
23: //#define DUMP_IO
24:
25: /* OF client interface. r3 points to the argument array. On return,
26: * r3 should contain 0==true or -1==false. r4-r12,cr0,cr1 may
27: * be modified freely.
28: *
29: * -1 should only be returned if the control transfer to OF fails
30: * (it doesn't) or if the function is unimplemented.
31: */
32:
33: #define PROM_MAX_ARGS 10
34: typedef struct prom_args {
35: prom_uarg_t service;
36: prom_arg_t nargs;
37: prom_arg_t nret;
38: prom_uarg_t args[PROM_MAX_ARGS];
39: } __attribute__((packed)) prom_args_t;
40:
41: static inline const char *
42: arg2pointer(prom_uarg_t value)
43: {
44: return (char*)(uintptr_t)value;
45: }
46:
47: static inline const char *
48: get_service(prom_args_t *pb)
49: {
50: return arg2pointer(pb->service);
51: }
52:
53: #ifdef DEBUG_CIF
54: static void memdump(const char *mem, unsigned long size)
55: {
56: int i;
57:
58: if (size == (unsigned long) -1)
59: return;
60:
61: for (i = 0; i < size; i += 16) {
62: int j;
63:
64: printk("0x%08lx ", (unsigned long)mem + i);
65:
66: for (j = 0; j < 16 && i + j < size; j++)
67: printk(" %02x", *(unsigned char*)(mem + i + j));
68:
69: for ( ; j < 16; j++)
70: printk(" __");
71:
72: printk(" ");
73:
74: for (j = 0; j < 16 && i + j < size; j++) {
75: unsigned char c = *(mem + i + j);
76: if (isprint(c))
77: printk("%c", c);
78: else
79: printk(".");
80: }
81: printk("\n");
82: }
83: }
84:
85: static void dump_service(prom_args_t *pb)
86: {
87: int i;
88: const char *service = get_service(pb);
89: if (strcmp(service, "test") == 0) {
90: printk("test(\"%s\") = ", arg2pointer(pb->args[0]));
91: } else if (strcmp(service, "peer") == 0) {
92: printk("peer(0x" FMT_prom_uargx ") = ", pb->args[0]);
93: } else if (strcmp(service, "child") == 0) {
94: printk("child(0x" FMT_prom_uargx ") = ", pb->args[0]);
95: } else if (strcmp(service, "parent") == 0) {
96: printk("parent(0x" FMT_prom_uargx ") = ", pb->args[0]);
97: } else if (strcmp(service, "instance-to-package") == 0) {
98: printk("instance-to-package(0x" FMT_prom_uargx ") = ", pb->args[0]);
99: } else if (strcmp(service, "getproplen") == 0) {
100: printk("getproplen(0x" FMT_prom_uargx ", \"%s\") = ",
101: pb->args[0], arg2pointer(pb->args[1]));
102: } else if (strcmp(service, "getprop") == 0) {
103: printk("getprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
104: pb->args[0], arg2pointer(pb->args[1]),
105: pb->args[2], pb->args[3]);
106: } else if (strcmp(service, "nextprop") == 0) {
107: printk("nextprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ") = ",
108: pb->args[0], arg2pointer(pb->args[1]), pb->args[2]);
109: } else if (strcmp(service, "setprop") == 0) {
110: printk("setprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
111: pb->args[0], arg2pointer(pb->args[1]),
112: pb->args[2], pb->args[3]);
113: memdump(arg2pointer(pb->args[2]), pb->args[3]);
114: printk(" = ");
115: } else if (strcmp(service, "canon") == 0) {
116: printk("canon(\"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
117: arg2pointer(pb->args[0]), pb->args[1], pb->args[2]);
118: } else if (strcmp(service, "finddevice") == 0) {
119: printk("finddevice(\"%s\") = ", arg2pointer(pb->args[0]));
120: } else if (strcmp(service, "instance-to-path") == 0) {
121: printk("instance-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
122: pb->args[0], pb->args[1], pb->args[2]);
123: } else if (strcmp(service, "package-to-path") == 0) {
124: printk("package-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
125: pb->args[0], pb->args[1], pb->args[2]);
126: } else if (strcmp(service, "open") == 0) {
127: printk("open(\"%s\") = ", arg2pointer(pb->args[0]));
128: } else if (strcmp(service, "close") == 0) {
129: printk("close(0x" FMT_prom_uargx ")\n", pb->args[0]);
130: } else if (strcmp(service, "read") == 0) {
131: #ifdef DUMP_IO
132: printk("read(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ",
133: pb->args[0], pb->args[1], pb->args[2]);
134: #endif
135: } else if (strcmp(service, "write") == 0) {
136: #ifdef DUMP_IO
137: printk("write(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
138: pb->args[0], pb->args[1], pb->args[2]);
139: memdump(arg2pointer(pb->args[1]), pb->args[2]);
140: printk(" = ");
141: #endif
142: } else if (strcmp(service, "seek") == 0) {
143: #ifdef DUMP_IO
144: printk("seek(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ") = ",
145: pb->args[0], pb->args[1], pb->args[2]);
146: #endif
147: } else if (strcmp(service, "claim") == 0) {
148: printk("claim(0x" FMT_prom_uargx ", " FMT_prom_arg ", " FMT_prom_arg ") = ",
149: pb->args[0], pb->args[1], pb->args[2]);
150: } else if (strcmp(service, "release") == 0) {
151: printk("release(0x" FMT_prom_uargx ", " FMT_prom_arg ")\n",
152: pb->args[0], pb->args[1]);
153: } else if (strcmp(service, "boot") == 0) {
154: printk("boot \"%s\"\n", arg2pointer(pb->args[0]));
155: } else if (strcmp(service, "enter") == 0) {
156: printk("enter()\n");
157: } else if (strcmp(service, "exit") == 0) {
158: printk("exit()\n");
159: } else if (strcmp(service, "test-method") == 0) {
160: printk("test-method(0x" FMT_prom_uargx ", \"%s\") = ",
161: pb->args[0], arg2pointer(pb->args[1]));
162: } else {
163: printk("of_client_interface: %s", service);
164: for( i = 0; i < pb->nargs; i++ )
165: printk(" " FMT_prom_uargx, pb->args[i]);
166: printk("\n");
167: }
168: }
169:
170: static void dump_return(prom_args_t *pb)
171: {
172: int i;
173: const char *service = get_service(pb);
174: if (strcmp(service, "test") == 0) {
175: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
176: } else if (strcmp(service, "peer") == 0) {
177: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
178: } else if (strcmp(service, "child") == 0) {
179: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
180: } else if (strcmp(service, "parent") == 0) {
181: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
182: } else if (strcmp(service, "instance-to-package") == 0) {
183: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
184: } else if (strcmp(service, "getproplen") == 0) {
185: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
186: } else if (strcmp(service, "getprop") == 0) {
187: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
188: if ((prom_arg_t)pb->args[pb->nargs] != -1)
189: memdump(arg2pointer(pb->args[2]), MIN(pb->args[3], pb->args[pb->nargs]));
190: } else if (strcmp(service, "nextprop") == 0) {
191: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
192: memdump(arg2pointer(pb->args[2]), pb->args[pb->nargs]);
193: } else if (strcmp(service, "setprop") == 0) {
194: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
195: } else if (strcmp(service, "canon") == 0) {
196: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
197: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
198: } else if (strcmp(service, "finddevice") == 0) {
199: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
200: } else if (strcmp(service, "instance-to-path") == 0) {
201: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
202: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
203: } else if (strcmp(service, "package-to-path") == 0) {
204: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
205: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
206: } else if (strcmp(service, "open") == 0) {
207: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
208: } else if (strcmp(service, "close") == 0) {
209: /* do nothing */
210: } else if (strcmp(service, "read") == 0) {
211: #ifdef DUMP_IO
212: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
213: memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]);
214: #endif
215: } else if (strcmp(service, "write") == 0) {
216: #ifdef DUMP_IO
217: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
218: #endif
219: } else if (strcmp(service, "seek") == 0) {
220: #ifdef DUMP_IO
221: printk(FMT_prom_arg "\n", pb->args[pb->nargs]);
222: #endif
223: } else if (strcmp(service, "claim") == 0) {
224: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
225: } else if (strcmp(service, "release") == 0) {
226: /* do nothing */
227: } else if (strcmp(service, "boot") == 0) {
228: /* do nothing */
229: } else if (strcmp(service, "enter") == 0) {
230: /* do nothing */
231: } else if (strcmp(service, "exit") == 0) {
232: /* do nothing */
233: } else if (strcmp(service, "test-method") == 0) {
234: printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]);
235: } else {
236: printk("of_client_interface return:");
237: for (i = 0; i < pb->nret; i++) {
238: printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]);
239: }
240: printk("\n");
241: }
242: }
243: #endif
244:
245: /* call-method, interpret */
246: static int
247: handle_calls( prom_args_t *pb )
248: {
249: int i, dstacksave = dstackcnt;
250: prom_uarg_t val;
251:
252: #ifdef DEBUG_CIF
253: printk("%s %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
254: get_service(pb), arg2pointer(pb->args[0]), pb->nargs, pb->nret);
255: #endif
256:
257: for( i=pb->nargs-1; i>=0; i-- )
258: PUSH( pb->args[i] );
259:
260: push_str(get_service(pb));
261: fword("client-call-iface");
262:
263: /* Drop the return code from client-call-iface (status is handled by the
264: catch result which is the first parameter below) */
265: POP();
266:
267: for( i=0; i<pb->nret; i++ ) {
268: val = POP();
269: pb->args[pb->nargs + i] = val;
270:
271: /* don't pop args if an exception occured */
272: if( !i && val )
273: break;
274: }
275:
276: #ifdef DEBUG_CIF
277: /* useful for debug but not necessarily an error */
278: if (i != pb->nret || dstackcnt != dstacksave) {
279: printk("%s '%s': possible argument error (" FMT_prom_arg "--" FMT_prom_arg ") got %d\n",
280: get_service(pb), arg2pointer(pb->args[0]),
281: pb->nargs - 2, pb->nret, i);
282: }
283:
284: printk("handle_calls return:");
285: for (i = 0; i < pb->nret; i++) {
286: printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]);
287: }
288: printk("\n");
289: #endif
290:
291: dstackcnt = dstacksave;
292: return 0;
293: }
294:
295: int
296: of_client_interface( int *params )
297: {
298: prom_args_t *pb = (prom_args_t*)params;
299: int val, i, dstacksave;
300:
301: if( pb->nargs < 0 || pb->nret < 0 ||
302: pb->nargs + pb->nret > PROM_MAX_ARGS)
303: return -1;
304:
305: #ifdef DEBUG_CIF
306: dump_service(pb);
307: #endif
308:
309: /* call-method exceptions are special */
310: if (!strcmp("call-method", get_service(pb)) || !strcmp("interpret", get_service(pb)))
311: return handle_calls( pb );
312:
313: dstacksave = dstackcnt;
314: for( i=pb->nargs-1; i>=0; i-- )
315: PUSH( pb->args[i] );
316:
317: push_str(get_service(pb));
318: fword("client-iface");
319:
320: if( (val=POP()) ) {
321: dstackcnt = dstacksave;
322: if( val == -1 )
323: printk("Unimplemented service %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
324: get_service(pb), pb->nargs, pb->nret );
325: #ifdef DEBUG_CIF
326: else
327: printk("ERROR!\n");
328: #endif
329: return -1;
330: }
331:
332: for( i=0; i<pb->nret ; i++ )
333: pb->args[pb->nargs + i] = POP();
334:
335: if( dstackcnt != dstacksave ) {
336: #ifdef DEBUG_CIF
337: printk("service %s: possible argument error (%d %d)\n",
338: get_service(pb), i, dstackcnt - dstacksave );
339: #endif
340: /* Some clients request less parameters than the CIF method
341: returns, e.g. getprop with OpenSolaris. Hence we drop any
342: stack parameters after issuing a warning above */
343: dstackcnt = dstacksave;
344: }
345:
346: #ifdef DEBUG_CIF
347: dump_return(pb);
348: #endif
349: return 0;
350: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.