ppc: Increase #address-cells for ppc64
[openbios/afaerber.git] / libopenbios / client.c
blobd8a9fdf8b106d335bb4e08f28a70ae78dac5320f
1 /*
2 * Creation Date: <2003/11/25 14:29:08 samuel>
3 * Time-stamp: <2004/03/27 01:13:53 samuel>
5 * <client.c>
7 * OpenFirmware client interface
9 * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
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
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/of.h"
21 /* Uncomment to enable debug printout of client interface calls */
22 //#define DEBUG_CIF
23 //#define DUMP_IO
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.
29 * -1 should only be returned if the control transfer to OF fails
30 * (it doesn't) or if the function is unimplemented.
33 #define PROM_MAX_ARGS 10
34 typedef struct prom_args {
35 const char *service;
36 long nargs;
37 long nret;
38 unsigned long args[PROM_MAX_ARGS];
39 } prom_args_t;
41 #ifdef DEBUG_CIF
42 static void memdump(const char *mem, unsigned long size)
44 int i;
46 if (size == (unsigned long) -1)
47 return;
49 for (i = 0; i < size; i += 16) {
50 int j;
52 printk("0x%08lx ", (unsigned long)mem + i);
54 for (j = 0; j < 16 && i + j < size; j++)
55 printk(" %02x", *(unsigned char*)(mem + i + j));
57 for ( ; j < 16; j++)
58 printk(" __");
60 printk(" ");
62 for (j = 0; j < 16 && i + j < size; j++) {
63 unsigned char c = *(mem + i + j);
64 if (isprint(c))
65 printk("%c", c);
66 else
67 printk(".");
69 printk("\n");
73 static void dump_service(prom_args_t *pb)
75 int i;
76 if (strcmp(pb->service, "test") == 0) {
77 printk("test(\"%s\") = ", (char*)pb->args[0]);
78 } else if (strcmp(pb->service, "peer") == 0) {
79 printk("peer(0x%08lx) = ", pb->args[0]);
80 } else if (strcmp(pb->service, "child") == 0) {
81 printk("child(0x%08lx) = ", pb->args[0]);
82 } else if (strcmp(pb->service, "parent") == 0) {
83 printk("parent(0x%08lx) = ", pb->args[0]);
84 } else if (strcmp(pb->service, "instance-to-package") == 0) {
85 printk("instance-to-package(0x%08lx) = ", pb->args[0]);
86 } else if (strcmp(pb->service, "getproplen") == 0) {
87 printk("getproplen(0x%08lx, \"%s\") = ",
88 pb->args[0], (char*)pb->args[1]);
89 } else if (strcmp(pb->service, "getprop") == 0) {
90 printk("getprop(0x%08lx, \"%s\", 0x%08lx, %ld) = ",
91 pb->args[0], (char*)pb->args[1],
92 pb->args[2], pb->args[3]);
93 } else if (strcmp(pb->service, "nextprop") == 0) {
94 printk("nextprop(0x%08lx, \"%s\", 0x%08lx) = ",
95 pb->args[0], (char*)pb->args[1], pb->args[2]);
96 } else if (strcmp(pb->service, "setprop") == 0) {
97 printk("setprop(0x%08lx, \"%s\", 0x%08lx, %ld)\n",
98 pb->args[0], (char*)pb->args[1],
99 pb->args[2], pb->args[3]);
100 memdump((char*)pb->args[2], pb->args[3]);
101 printk(" = ");
102 } else if (strcmp(pb->service, "canon") == 0) {
103 printk("canon(\"%s\", 0x%08lx, %ld)\n",
104 (char*)pb->args[0], pb->args[1], pb->args[2]);
105 } else if (strcmp(pb->service, "finddevice") == 0) {
106 printk("finddevice(\"%s\") = ", (char*)pb->args[0]);
107 } else if (strcmp(pb->service, "instance-to-path") == 0) {
108 printk("instance-to-path(0x%08lx, 0x%08lx, %ld) = ",
109 pb->args[0], pb->args[1], pb->args[2]);
110 } else if (strcmp(pb->service, "package-to-path") == 0) {
111 printk("package-to-path(0x%08lx, 0x%08lx, %ld) = ",
112 pb->args[0], pb->args[1], pb->args[2]);
113 } else if (strcmp(pb->service, "open") == 0) {
114 printk("open(\"%s\") = ", (char*)pb->args[0]);
115 } else if (strcmp(pb->service, "close") == 0) {
116 printk("close(0x%08lx)\n", pb->args[0]);
117 } else if (strcmp(pb->service, "read") == 0) {
118 #ifdef DUMP_IO
119 printk("read(0x%08lx, 0x%08lx, %ld) = ",
120 pb->args[0], pb->args[1], pb->args[2]);
121 #endif
122 } else if (strcmp(pb->service, "write") == 0) {
123 #ifdef DUMP_IO
124 printk("write(0x%08lx, 0x%08lx, %ld)\n",
125 pb->args[0], pb->args[1], pb->args[2]);
126 memdump((char*)pb->args[1], pb->args[2]);
127 printk(" = ");
128 #endif
129 } else if (strcmp(pb->service, "seek") == 0) {
130 #ifdef DUMP_IO
131 printk("seek(0x%08lx, 0x%08lx, 0x%08lx) = ",
132 pb->args[0], pb->args[1], pb->args[2]);
133 #endif
134 } else if (strcmp(pb->service, "claim") == 0) {
135 printk("claim(0x%08lx, %ld, %ld) = ",
136 pb->args[0], pb->args[1], pb->args[2]);
137 } else if (strcmp(pb->service, "release") == 0) {
138 printk("release(0x%08lx, %ld)\n",
139 pb->args[0], pb->args[1]);
140 } else if (strcmp(pb->service, "boot") == 0) {
141 printk("boot \"%s\"\n", (char*)pb->args[0]);
142 } else if (strcmp(pb->service, "enter") == 0) {
143 printk("enter()\n");
144 } else if (strcmp(pb->service, "exit") == 0) {
145 printk("exit()\n");
146 } else if (strcmp(pb->service, "test-method") == 0) {
147 printk("test-method(0x%08lx, \"%s\") = ",
148 pb->args[0], (char*)pb->args[1]);
149 } else {
150 printk("of_client_interface: %s ", pb->service );
151 for( i = 0; i < pb->nargs; i++ )
152 printk("%lx ", pb->args[i] );
153 printk("\n");
157 static void dump_return(prom_args_t *pb)
159 int i;
160 if (strcmp(pb->service, "test") == 0) {
161 printk(" %ld\n", pb->args[pb->nargs]);
162 } else if (strcmp(pb->service, "peer") == 0) {
163 printk("0x%08lx\n", pb->args[pb->nargs]);
164 } else if (strcmp(pb->service, "child") == 0) {
165 printk("0x%08lx\n", pb->args[pb->nargs]);
166 } else if (strcmp(pb->service, "parent") == 0) {
167 printk("0x%08lx\n", pb->args[pb->nargs]);
168 } else if (strcmp(pb->service, "instance-to-package") == 0) {
169 printk("0x%08lx\n", pb->args[pb->nargs]);
170 } else if (strcmp(pb->service, "getproplen") == 0) {
171 printk("0x%08lx\n", pb->args[pb->nargs]);
172 } else if (strcmp(pb->service, "getprop") == 0) {
173 printk("%ld\n", pb->args[pb->nargs]);
174 if ((long)pb->args[pb->nargs] != -1)
175 memdump((char*)pb->args[2], MIN(pb->args[3], pb->args[pb->nargs]));
176 } else if (strcmp(pb->service, "nextprop") == 0) {
177 printk("%ld\n", pb->args[pb->nargs]);
178 memdump((char*)pb->args[2], pb->args[pb->nargs]);
179 } else if (strcmp(pb->service, "setprop") == 0) {
180 printk("%ld\n", pb->args[pb->nargs]);
181 } else if (strcmp(pb->service, "canon") == 0) {
182 printk("%ld\n", pb->args[pb->nargs]);
183 memdump((char*)pb->args[1], pb->args[pb->nargs]);
184 } else if (strcmp(pb->service, "finddevice") == 0) {
185 printk("0x%08lx\n", pb->args[pb->nargs]);
186 } else if (strcmp(pb->service, "instance-to-path") == 0) {
187 printk("%ld\n", pb->args[pb->nargs]);
188 memdump((char*)pb->args[1], pb->args[pb->nargs]);
189 } else if (strcmp(pb->service, "package-to-path") == 0) {
190 printk("%ld\n", pb->args[pb->nargs]);
191 memdump((char*)pb->args[1], pb->args[pb->nargs]);
192 } else if (strcmp(pb->service, "open") == 0) {
193 printk("0x%08lx\n", pb->args[pb->nargs]);
194 } else if (strcmp(pb->service, "close") == 0) {
195 /* do nothing */
196 } else if (strcmp(pb->service, "read") == 0) {
197 #ifdef DUMP_IO
198 printk("%ld\n", pb->args[pb->nargs]);
199 memdump((char*)pb->args[1], pb->args[pb->nargs]);
200 #endif
201 } else if (strcmp(pb->service, "write") == 0) {
202 #ifdef DUMP_IO
203 printk("%ld\n", pb->args[pb->nargs]);
204 #endif
205 } else if (strcmp(pb->service, "seek") == 0) {
206 #ifdef DUMP_IO
207 printk("%ld\n", pb->args[pb->nargs]);
208 #endif
209 } else if (strcmp(pb->service, "claim") == 0) {
210 printk("0x%08lx\n", pb->args[pb->nargs]);
211 } else if (strcmp(pb->service, "release") == 0) {
212 /* do nothing */
213 } else if (strcmp(pb->service, "boot") == 0) {
214 /* do nothing */
215 } else if (strcmp(pb->service, "enter") == 0) {
216 /* do nothing */
217 } else if (strcmp(pb->service, "exit") == 0) {
218 /* do nothing */
219 } else if (strcmp(pb->service, "test-method") == 0) {
220 printk("0x%08lx\n", pb->args[pb->nargs]);
221 } else {
222 printk("of_client_interface return:");
223 for (i = 0; i < pb->nret; i++) {
224 printk(" %lx", pb->args[pb->nargs + i]);
226 printk("\n");
229 #endif
231 /* call-method, interpret */
232 static int
233 handle_calls( prom_args_t *pb )
235 int i, dstacksave = dstackcnt;
236 long val;
238 #ifdef DEBUG_CIF
239 printk("%s %s ([%ld] -- [%ld])\n", pb->service, (char *)pb->args[0],
240 pb->nargs, pb->nret);
241 #endif
243 for( i=pb->nargs-1; i>=0; i-- )
244 PUSH( pb->args[i] );
246 push_str( pb->service );
247 fword("client-call-iface");
249 /* Drop the return code from client-call-iface (status is handled by the
250 catch result which is the first parameter below) */
251 POP();
253 for( i=0; i<pb->nret; i++ ) {
254 val = POP();
255 pb->args[pb->nargs + i] = val;
257 /* don't pop args if an exception occured */
258 if( !i && val )
259 break;
262 #ifdef DEBUG_CIF
263 /* useful for debug but not necessarily an error */
264 if( i != pb->nret || dstackcnt != dstacksave ) {
265 printk("%s '%s': possible argument error (%ld--%ld) got %d\n",
266 pb->service, (char*)pb->args[0], pb->nargs-2, pb->nret, i );
269 printk("handle_calls return: ");
270 for (i = 0; i < pb->nret; i++) {
271 printk("%lx ", pb->args[pb->nargs + i]);
273 printk("\n");
274 #endif
276 dstackcnt = dstacksave;
277 return 0;
281 of_client_interface( int *params )
283 prom_args_t *pb = (prom_args_t*)params;
284 int val, i, dstacksave;
286 if( pb->nargs < 0 || pb->nret < 0 ||
287 pb->nargs + pb->nret > PROM_MAX_ARGS)
288 return -1;
290 #ifdef DEBUG_CIF
291 dump_service(pb);
292 #endif
294 /* call-method exceptions are special */
295 if( !strcmp("call-method", pb->service) || !strcmp("interpret", pb->service) )
296 return handle_calls( pb );
298 dstacksave = dstackcnt;
299 for( i=pb->nargs-1; i>=0; i-- )
300 PUSH( pb->args[i] );
302 push_str( pb->service );
303 fword("client-iface");
305 if( (val=POP()) ) {
306 dstackcnt = dstacksave;
307 if( val == -1 )
308 printk("Unimplemented service %s ([%ld] -- [%ld])\n",
309 pb->service, pb->nargs, pb->nret );
310 #ifdef DEBUG_CIF
311 else
312 printk("ERROR!\n");
313 #endif
314 return -1;
317 for( i=0; i<pb->nret ; i++ )
318 pb->args[pb->nargs + i] = POP();
320 if( dstackcnt != dstacksave ) {
321 #ifdef DEBUG_CIF
322 printk("service %s: possible argument error (%d %d)\n",
323 pb->service, i, dstackcnt - dstacksave );
324 #endif
325 /* Some clients request less parameters than the CIF method
326 returns, e.g. getprop with OpenSolaris. Hence we drop any
327 stack parameters after issuing a warning above */
328 dstackcnt = dstacksave;
331 #ifdef DEBUG_CIF
332 dump_return(pb);
333 #endif
334 return 0;