2 * Creation Date: <2003/11/25 14:29:08 samuel>
3 * Time-stamp: <2004/03/27 01:13:53 samuel>
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
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/of.h"
21 /* Uncomment to enable debug printout of client interface calls */
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
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
{
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
);
54 static void memdump(const char *mem
, unsigned long size
)
58 if (size
== (unsigned long) -1)
61 for (i
= 0; i
< size
; i
+= 16) {
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
));
74 for (j
= 0; j
< 16 && i
+ j
< size
; j
++) {
75 unsigned char c
= *(mem
+ i
+ j
);
85 static void dump_service(prom_args_t
*pb
)
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]);
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) {
132 printk("read(0x" FMT_prom_uargx
", 0x" FMT_prom_uargx
", " FMT_prom_arg
") = ",
133 pb
->args
[0], pb
->args
[1], pb
->args
[2]);
135 } else if (strcmp(service
, "write") == 0) {
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]);
142 } else if (strcmp(service
, "seek") == 0) {
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]);
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) {
157 } else if (strcmp(service
, "exit") == 0) {
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]));
163 printk("of_client_interface: %s", service
);
164 for( i
= 0; i
< pb
->nargs
; i
++ )
165 printk(" " FMT_prom_uargx
, pb
->args
[i
]);
170 static void dump_return(prom_args_t
*pb
)
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) {
210 } else if (strcmp(service
, "read") == 0) {
212 printk(FMT_prom_arg
"\n", pb
->args
[pb
->nargs
]);
213 memdump(arg2pointer(pb
->args
[1]), pb
->args
[pb
->nargs
]);
215 } else if (strcmp(service
, "write") == 0) {
217 printk(FMT_prom_arg
"\n", pb
->args
[pb
->nargs
]);
219 } else if (strcmp(service
, "seek") == 0) {
221 printk(FMT_prom_arg
"\n", pb
->args
[pb
->nargs
]);
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) {
227 } else if (strcmp(service
, "boot") == 0) {
229 } else if (strcmp(service
, "enter") == 0) {
231 } else if (strcmp(service
, "exit") == 0) {
233 } else if (strcmp(service
, "test-method") == 0) {
234 printk("0x" FMT_prom_uargx
"\n", pb
->args
[pb
->nargs
]);
236 printk("of_client_interface return:");
237 for (i
= 0; i
< pb
->nret
; i
++) {
238 printk(" " FMT_prom_uargx
, pb
->args
[pb
->nargs
+ i
]);
245 /* call-method, interpret */
247 handle_calls( prom_args_t
*pb
)
249 int i
, dstacksave
= dstackcnt
;
253 printk("%s %s ([" FMT_prom_arg
"] -- [" FMT_prom_arg
"])\n",
254 get_service(pb
), arg2pointer(pb
->args
[0]), pb
->nargs
, pb
->nret
);
257 for( i
=pb
->nargs
-1; i
>=0; 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) */
267 for( i
=0; i
<pb
->nret
; i
++ ) {
269 pb
->args
[pb
->nargs
+ i
] = val
;
271 /* don't pop args if an exception occured */
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
]);
291 dstackcnt
= dstacksave
;
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
)
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
-- )
317 push_str(get_service(pb
));
318 fword("client-iface");
321 dstackcnt
= dstacksave
;
323 printk("Unimplemented service %s ([" FMT_prom_arg
"] -- [" FMT_prom_arg
"])\n",
324 get_service(pb
), pb
->nargs
, pb
->nret
);
332 for( i
=0; i
<pb
->nret
; i
++ )
333 pb
->args
[pb
->nargs
+ i
] = POP();
335 if( dstackcnt
!= dstacksave
) {
337 printk("service %s: possible argument error (%d %d)\n",
338 get_service(pb
), i
, dstackcnt
- dstacksave
);
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
;