ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / libopenbios / client.c
blobad9ccdcebe5b23d9a9cdf2e46a736879969dbe99
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 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;
41 static inline const char *
42 arg2pointer(prom_uarg_t value)
44 return (char*)(uintptr_t)value;
47 static inline const char *
48 get_service(prom_args_t *pb)
50 return arg2pointer(pb->service);
53 #ifdef DEBUG_CIF
54 static void memdump(const char *mem, unsigned long size)
56 int i;
58 if (size == (unsigned long) -1)
59 return;
61 for (i = 0; i < size; i += 16) {
62 int j;
64 printk("0x%08lx ", (unsigned long)mem + i);
66 for (j = 0; j < 16 && i + j < size; j++)
67 printk(" %02x", *(unsigned char*)(mem + i + j));
69 for ( ; j < 16; j++)
70 printk(" __");
72 printk(" ");
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(".");
81 printk("\n");
85 static void dump_service(prom_args_t *pb)
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");
170 static void dump_return(prom_args_t *pb)
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]);
240 printk("\n");
243 #endif
245 /* call-method, interpret */
246 static int
247 handle_calls( prom_args_t *pb )
249 int i, dstacksave = dstackcnt;
250 prom_uarg_t val;
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
257 for( i=pb->nargs-1; i>=0; i-- )
258 PUSH( pb->args[i] );
260 push_str(get_service(pb));
261 fword("client-call-iface");
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();
267 for( i=0; i<pb->nret; i++ ) {
268 val = POP();
269 pb->args[pb->nargs + i] = val;
271 /* don't pop args if an exception occured */
272 if( !i && val )
273 break;
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);
284 printk("handle_calls return:");
285 for (i = 0; i < pb->nret; i++) {
286 printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]);
288 printk("\n");
289 #endif
291 dstackcnt = dstacksave;
292 return 0;
296 of_client_interface( int *params )
298 prom_args_t *pb = (prom_args_t*)params;
299 int val, i, dstacksave;
301 if( pb->nargs < 0 || pb->nret < 0 ||
302 pb->nargs + pb->nret > PROM_MAX_ARGS)
303 return -1;
305 #ifdef DEBUG_CIF
306 dump_service(pb);
307 #endif
309 /* call-method exceptions are special */
310 if (!strcmp("call-method", get_service(pb)) || !strcmp("interpret", get_service(pb)))
311 return handle_calls( pb );
313 dstacksave = dstackcnt;
314 for( i=pb->nargs-1; i>=0; i-- )
315 PUSH( pb->args[i] );
317 push_str(get_service(pb));
318 fword("client-iface");
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;
332 for( i=0; i<pb->nret ; i++ )
333 pb->args[pb->nargs + i] = POP();
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;
346 #ifdef DEBUG_CIF
347 dump_return(pb);
348 #endif
349 return 0;