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 unsigned long args
[PROM_MAX_ARGS
];
42 static void memdump(const char *mem
, unsigned long size
)
46 if (size
== (unsigned long) -1)
49 for (i
= 0; i
< size
; i
+= 16) {
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
));
62 for (j
= 0; j
< 16 && i
+ j
< size
; j
++) {
63 unsigned char c
= *(mem
+ i
+ j
);
73 static void dump_service(prom_args_t
*pb
)
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]);
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) {
119 printk("read(0x%08lx, 0x%08lx, %ld) = ",
120 pb
->args
[0], pb
->args
[1], pb
->args
[2]);
122 } else if (strcmp(pb
->service
, "write") == 0) {
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]);
129 } else if (strcmp(pb
->service
, "seek") == 0) {
131 printk("seek(0x%08lx, 0x%08lx, 0x%08lx) = ",
132 pb
->args
[0], pb
->args
[1], pb
->args
[2]);
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) {
144 } else if (strcmp(pb
->service
, "exit") == 0) {
146 } else if (strcmp(pb
->service
, "test-method") == 0) {
147 printk("test-method(0x%08lx, \"%s\") = ",
148 pb
->args
[0], (char*)pb
->args
[1]);
150 printk("of_client_interface: %s ", pb
->service
);
151 for( i
= 0; i
< pb
->nargs
; i
++ )
152 printk("%lx ", pb
->args
[i
] );
157 static void dump_return(prom_args_t
*pb
)
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) {
196 } else if (strcmp(pb
->service
, "read") == 0) {
198 printk("%ld\n", pb
->args
[pb
->nargs
]);
199 memdump((char*)pb
->args
[1], pb
->args
[pb
->nargs
]);
201 } else if (strcmp(pb
->service
, "write") == 0) {
203 printk("%ld\n", pb
->args
[pb
->nargs
]);
205 } else if (strcmp(pb
->service
, "seek") == 0) {
207 printk("%ld\n", pb
->args
[pb
->nargs
]);
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) {
213 } else if (strcmp(pb
->service
, "boot") == 0) {
215 } else if (strcmp(pb
->service
, "enter") == 0) {
217 } else if (strcmp(pb
->service
, "exit") == 0) {
219 } else if (strcmp(pb
->service
, "test-method") == 0) {
220 printk("0x%08lx\n", pb
->args
[pb
->nargs
]);
222 printk("of_client_interface return:");
223 for (i
= 0; i
< pb
->nret
; i
++) {
224 printk(" %lx", pb
->args
[pb
->nargs
+ i
]);
231 /* call-method, interpret */
233 handle_calls( prom_args_t
*pb
)
235 int i
, dstacksave
= dstackcnt
;
239 printk("%s %s ([%ld] -- [%ld])\n", pb
->service
, (char *)pb
->args
[0],
240 pb
->nargs
, pb
->nret
);
243 for( i
=pb
->nargs
-1; i
>=0; 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) */
253 for( i
=0; i
<pb
->nret
; i
++ ) {
255 pb
->args
[pb
->nargs
+ i
] = val
;
257 /* don't pop args if an exception occured */
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
]);
276 dstackcnt
= dstacksave
;
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
)
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
-- )
302 push_str( pb
->service
);
303 fword("client-iface");
306 dstackcnt
= dstacksave
;
308 printk("Unimplemented service %s ([%ld] -- [%ld])\n",
309 pb
->service
, pb
->nargs
, pb
->nret
);
317 for( i
=0; i
<pb
->nret
; i
++ )
318 pb
->args
[pb
->nargs
+ i
] = POP();
320 if( dstackcnt
!= dstacksave
) {
322 printk("service %s: possible argument error (%d %d)\n",
323 pb
->service
, i
, dstackcnt
- dstacksave
);
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
;