Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / bindings.c
1 /*
2  *   Creation Date: <2003/11/24 12:30:18 samuel>
3  *   Time-stamp: <2004/01/07 19:37:38 samuel>
4  *
5  *      <bindings.c>
6  *
7  *      Forth bindings
8  *
9  *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
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 "libc/string.h"
20 #include "libc/stdlib.h"
21 #include "libc/byteorder.h"
22
23
24 /************************************************************************/
25 /*      forth interface glue                                            */
26 /************************************************************************/
27
28 void
29 push_str( const char *str )
30 {
31         PUSH( pointer2cell(str) );
32         PUSH( str ? strlen(str) : 0 );
33 }
34
35 /* WARNING: sloooow - AVOID */
36 cell
37 feval( const char *str )
38 {
39         push_str( str );
40         return eword("evaluate", 2);
41 }
42
43 cell
44 _eword( const char *word, xt_t *cache_xt, int nargs )
45 {
46         static xt_t catch_xt = 0;
47         cell ret = -1;
48
49         if( !catch_xt )
50                 catch_xt = findword("catch");
51         if( !*cache_xt )
52                 *cache_xt = findword( (char*)word );
53
54         if( *cache_xt ) {
55                 PUSH_xt( *cache_xt );
56                 enterforth( catch_xt );
57                 if( (ret=POP()) )
58                         dstackcnt -= nargs;
59         }
60         return ret;
61 }
62
63 /* note: only the built-in dictionary is searched */
64 int
65 _fword( const char *word, xt_t *cache_xt )
66 {
67         if( !*cache_xt )
68                 *cache_xt = findword( (char*)word );
69
70         if( *cache_xt ) {
71                 enterforth( *cache_xt );
72                 return 0;
73         }
74         return -1;
75 }
76
77 int
78 _selfword( const char *method, xt_t *cache_xt )
79 {
80         if( !*cache_xt )
81                 *cache_xt = find_ih_method( method, my_self() );
82         if( *cache_xt ) {
83                 enterforth( *cache_xt );
84                 return 0;
85         }
86         return -1;
87 }
88
89 int
90 _parword( const char *method, xt_t *cache_xt )
91 {
92         if( !*cache_xt )
93                 *cache_xt = find_ih_method( method, my_parent() );
94         if( *cache_xt ) {
95                 enterforth( *cache_xt );
96                 return 0;
97         }
98         return -1;
99 }
100
101 void
102 bind_func( const char *name, void (*func)(void) )
103 {
104         PUSH( pointer2cell(func) );
105         push_str( name );
106         fword("is-cfunc");
107 }
108
109 void
110 bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) )
111 {
112         PUSH_xt( xt );
113         PUSH( arg );
114         PUSH( pointer2cell(func) );
115         push_str( name );
116         fword("is-xt-cfunc");
117 }
118
119 xt_t
120 bind_noname_func( void (*func)(void) )
121 {
122         PUSH( pointer2cell(func) );
123         fword("is-noname-cfunc");
124         return POP_xt();
125 }
126
127 void
128 throw( int error )
129 {
130         PUSH( error );
131         fword("throw");
132 }
133
134
135 /************************************************************************/
136 /*      ihandle related                                                 */
137 /************************************************************************/
138
139 phandle_t
140 ih_to_phandle( ihandle_t ih )
141 {
142         PUSH_ih( ih );
143         fword("ihandle>phandle");
144         return POP_ph();
145 }
146
147 ihandle_t
148 my_parent( void )
149 {
150         fword("my-parent");
151         return POP_ih();
152 }
153
154 ihandle_t
155 my_self( void )
156 {
157         fword("my-self");
158         return POP_ih();
159 }
160
161 xt_t
162 find_package_method( const char *method, phandle_t ph )
163 {
164         push_str( method );
165         PUSH_ph( ph );
166         fword("find-method");
167         if( POP() )
168                 return POP_xt();
169         return 0;
170 }
171
172 xt_t
173 find_ih_method( const char *method, ihandle_t ih )
174 {
175         return find_package_method( method, ih_to_phandle(ih) );
176 }
177
178
179 xt_t
180 find_parent_method( const char *method )
181 {
182         return find_ih_method( method, my_parent() );
183 }
184
185 void
186 call_package( xt_t xt, ihandle_t ihandle )
187 {
188         PUSH_xt( xt );
189         PUSH_ih( ihandle );
190         fword("call-package");
191 }
192
193 void
194 call_parent( xt_t xt )
195 {
196         PUSH_xt( xt );
197         fword("call-parent");
198 }
199
200 void
201 call_parent_method( const char *method )
202 {
203         push_str( method );
204         fword("$call-parent");
205 }
206
207
208 /************************************************************************/
209 /*      open/close package/dev                                          */
210 /************************************************************************/
211
212 ihandle_t
213 open_dev( const char *spec )
214 {
215         push_str( spec );
216         fword("open-dev");
217         return POP_ih();
218 }
219
220 void
221 close_dev( ihandle_t ih )
222 {
223         PUSH_ih( ih );
224         fword("close-dev");
225 }
226
227 ihandle_t
228 open_package( const char *argstr, phandle_t ph )
229 {
230         push_str( argstr );
231         PUSH_ph( ph );
232         fword("open-package");
233         return POP_ih();
234 }
235
236 void
237 close_package( ihandle_t ih )
238 {
239         PUSH_ih( ih );
240         fword("close-package");
241 }
242
243
244 /************************************************************************/
245 /*      ihandle arguments                                               */
246 /************************************************************************/
247
248 char *
249 pop_fstr_copy( void )
250 {
251         int len = POP();
252         char *str, *p = (char*)cell2pointer(POP());
253         if( !len )
254                 return NULL;
255         str = malloc( len + 1 );
256         if( !str )
257                 return NULL;
258         memcpy( str, p, len );
259         str[len] = 0;
260         return str;
261 }
262
263 char *
264 my_args_copy( void )
265 {
266         fword("my-args");
267         return pop_fstr_copy();
268 }
269
270
271 /************************************************************************/
272 /*      properties                                                      */
273 /************************************************************************/
274
275 void
276 set_property( phandle_t ph, const char *name, const char *buf, int len )
277 {
278         if( !ph ) {
279                 printk("set_property: NULL phandle\n");
280                 return;
281         }
282         PUSH(pointer2cell(buf));
283         PUSH(len);
284         push_str( name );
285         PUSH_ph(ph);
286         fword("set-property");
287 }
288
289 void
290 set_int_property( phandle_t ph, const char *name, u32 val )
291 {
292         u32 swapped=__cpu_to_be32(val);
293         set_property( ph, name, (char*)&swapped, sizeof(swapped) );
294 }
295
296 char *
297 get_property( phandle_t ph, const char *name, int *retlen )
298 {
299         int len;
300
301         if( retlen )
302                 *retlen = -1;
303
304         push_str( name );
305         PUSH_ph( ph );
306         fword("get-package-property");
307         if( POP() )
308                 return NULL;
309         len = POP();
310         if( retlen )
311                 *retlen = len;
312         return (char*)cell2pointer(POP());
313 }
314
315 u32
316 get_int_property( phandle_t ph, const char *name, int *retlen )
317 {
318         u32 *p;
319
320         if( !(p=(u32 *)get_property(ph, name, retlen)) )
321                 return 0;
322         return __be32_to_cpu(*p);
323 }
324
325
326 /************************************************************************/
327 /*      device selection / iteration                                    */
328 /************************************************************************/
329
330 void
331 activate_dev( phandle_t ph )
332 {
333         PUSH_ph( ph );
334         fword("active-package!");
335 }
336
337 phandle_t
338 activate_device( const char *str )
339 {
340         phandle_t ph = find_dev( str );
341         activate_dev( ph );
342         return ph;
343 }
344
345 void
346 device_end( void )
347 {
348         fword("device-end");
349 }
350
351 phandle_t
352 get_cur_dev( void )
353 {
354         fword("active-package");
355         return POP_ph();
356 }
357
358 phandle_t
359 find_dev( const char *path )
360 {
361         phandle_t ret = 0;
362         push_str( path );
363         fword("(find-dev)");
364         if( POP() )
365                 return POP_ph();
366         return ret;
367 }
368
369 phandle_t
370 dt_iter_begin( void )
371 {
372         fword("iterate-tree-begin");
373         return POP_ph();
374 }
375
376 phandle_t
377 dt_iterate( phandle_t last_tree )
378 {
379         if( !last_tree )
380                 return dt_iter_begin();
381
382         PUSH_ph( last_tree );
383         fword("iterate-tree");
384         return POP_ph();
385 }
386
387 phandle_t
388 dt_iterate_type( phandle_t last_tree, const char *type )
389 {
390         if( !last_tree )
391                 last_tree = dt_iter_begin();
392
393         /* root node is never matched but we don't care about that */
394         while( (last_tree = dt_iterate(last_tree)) ) {
395                 char *s = get_property( last_tree, "device_type", NULL );
396                 if( s && !strcmp(type, s) )
397                         break;
398         }
399         return last_tree;
400 }
401
402
403 /************************************************************************/
404 /*      node methods                                                    */
405 /************************************************************************/
406
407 void
408 make_openable( int only_parents )
409 {
410         phandle_t ph, save_ph = get_cur_dev();
411         PUSH_ph( save_ph );
412
413         for( ;; ) {
414                 if( only_parents++ )
415                         fword("parent");
416                 if( !(ph=POP_ph()) )
417                         break;
418                 activate_dev( ph );
419                 PUSH_ph( ph );
420                 fword("is-open");
421         }
422         activate_dev( save_ph );
423 }
424
425 static void
426 call1_func( void )
427 {
428         void (*func)(cell v);
429         func = (void*)cell2pointer(POP());
430
431         (*func)( POP() );
432 }
433
434
435 static void
436 add_methods( int flags, int size, const method_t *methods, int nmet )
437 {
438         xt_t xt=0;
439         int i;
440
441         /* nodes might be matched multiple times */
442         if( find_package_method(methods[0].name, get_cur_dev()) )
443                 return;
444
445         if( size ) {
446                 PUSH( size );
447                 fword("is-ibuf");
448                 xt = POP_xt();
449         }
450
451         for( i=0; i<nmet; i++ ) {
452                 /* null-name methods specify static initializers */
453                 if( !methods[i].name ) {
454                         typedef void (*initfunc)( void *p );
455                         char *buf = NULL;
456                         if( xt ) {
457                                 enterforth( xt );
458                                 buf = (char*)cell2pointer(POP());
459                         }
460                         (*(initfunc)methods[i].func)( buf );
461                         continue;
462                 }
463                 if( !size )
464                         bind_func( methods[i].name, methods[i].func );
465                 else
466                         bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func),
467                                      &call1_func );
468         }
469
470         if( flags & INSTALL_OPEN )
471                 make_openable(0);
472 }
473
474 void
475 bind_node( int flags, int size, const char * const *paths, int npaths,
476            const method_t *methods, int nmet )
477 {
478         phandle_t save_ph = get_cur_dev();
479         int i;
480
481         for( i=0; i<npaths; i++ ) {
482                 const char *name = paths[i];
483
484                 /* type matching? */
485                 if( *name == 'T' ) {
486                         phandle_t ph = 0;
487                         name++;
488                         while( (ph=dt_iterate_type(ph, name)) ) {
489                                 activate_dev( ph );
490                                 add_methods( flags, size, methods, nmet );
491                         }
492                         continue;
493                 }
494
495                 /* path patching */
496                 if( activate_device(name) )
497                         add_methods( flags, size, methods, nmet );
498                 else if( *name == '+' ) {
499                         /* create node (and missing parents) */
500                         if( !activate_device(++name) ) {
501                                 push_str( name );
502                                 fword("create-node");
503                         }
504                         add_methods( flags, size, methods, nmet );
505                 }
506         }
507         activate_dev( save_ph );
508 }
509
510 phandle_t
511 bind_new_node( int flags, int size, const char *name,
512            const method_t *methods, int nmet )
513 {
514         phandle_t save_ph = get_cur_dev();
515         phandle_t new_ph;
516         /* create node */
517         push_str( name );
518         fword("create-node");
519         add_methods( flags, size, methods, nmet );
520     new_ph = get_cur_dev();
521
522         activate_dev( save_ph );
523         return new_ph;
524 }