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
push_str(const char * str)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
feval(const char * str)37 feval( const char *str )
38 {
39 push_str( str );
40 return eword("evaluate", 2);
41 }
42
43 cell
_eword(const char * word,xt_t * cache_xt,int nargs)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
_fword(const char * word,xt_t * cache_xt)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
_selfword(const char * method,xt_t * cache_xt)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
_parword(const char * method,xt_t * cache_xt)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
bind_func(const char * name,void (* func)(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
bind_xtfunc(const char * name,xt_t xt,ucell arg,void (* func)(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
bind_noname_func(void (* func)(void))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
throw(int error)128 throw( int error )
129 {
130 PUSH( error );
131 fword("throw");
132 }
133
134
135 /************************************************************************/
136 /* ihandle related */
137 /************************************************************************/
138
139 phandle_t
ih_to_phandle(ihandle_t ih)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
my_parent(void)148 my_parent( void )
149 {
150 fword("my-parent");
151 return POP_ih();
152 }
153
154 ihandle_t
my_self(void)155 my_self( void )
156 {
157 fword("my-self");
158 return POP_ih();
159 }
160
161 xt_t
find_package_method(const char * method,phandle_t ph)162 find_package_method( const char *method, phandle_t ph )
163 {
164 if (method == NULL) {
165 push_str("");
166 } else {
167 push_str( method );
168 }
169
170 PUSH_ph( ph );
171 fword("find-method");
172 if( POP() )
173 return POP_xt();
174 return 0;
175 }
176
177 xt_t
find_ih_method(const char * method,ihandle_t ih)178 find_ih_method( const char *method, ihandle_t ih )
179 {
180 return find_package_method( method, ih_to_phandle(ih) );
181 }
182
183
184 xt_t
find_parent_method(const char * method)185 find_parent_method( const char *method )
186 {
187 return find_ih_method( method, my_parent() );
188 }
189
190 void
call_package(xt_t xt,ihandle_t ihandle)191 call_package( xt_t xt, ihandle_t ihandle )
192 {
193 PUSH_xt( xt );
194 PUSH_ih( ihandle );
195 fword("call-package");
196 }
197
198 void
call_parent(xt_t xt)199 call_parent( xt_t xt )
200 {
201 PUSH_xt( xt );
202 fword("call-parent");
203 }
204
205 void
call_parent_method(const char * method)206 call_parent_method( const char *method )
207 {
208 push_str( method );
209 fword("$call-parent");
210 }
211
212
213 /************************************************************************/
214 /* open/close package/dev */
215 /************************************************************************/
216
217 ihandle_t
open_dev(const char * spec)218 open_dev( const char *spec )
219 {
220 push_str( spec );
221 fword("open-dev");
222 return POP_ih();
223 }
224
225 void
close_dev(ihandle_t ih)226 close_dev( ihandle_t ih )
227 {
228 PUSH_ih( ih );
229 fword("close-dev");
230 }
231
232 ihandle_t
open_package(const char * argstr,phandle_t ph)233 open_package( const char *argstr, phandle_t ph )
234 {
235 push_str( argstr );
236 PUSH_ph( ph );
237 fword("open-package");
238 return POP_ih();
239 }
240
241 void
close_package(ihandle_t ih)242 close_package( ihandle_t ih )
243 {
244 PUSH_ih( ih );
245 fword("close-package");
246 }
247
248
249 /************************************************************************/
250 /* ihandle arguments */
251 /************************************************************************/
252
253 char *
pop_fstr_copy(void)254 pop_fstr_copy( void )
255 {
256 int len = POP();
257 char *str, *p = (char*)cell2pointer(POP());
258 if( !len )
259 return NULL;
260 str = malloc( len + 1 );
261 if( !str )
262 return NULL;
263 memcpy( str, p, len );
264 str[len] = 0;
265 return str;
266 }
267
268 char *
my_args_copy(void)269 my_args_copy( void )
270 {
271 fword("my-args");
272 return pop_fstr_copy();
273 }
274
275
276 /************************************************************************/
277 /* properties */
278 /************************************************************************/
279
280 void
set_property(phandle_t ph,const char * name,const char * buf,int len)281 set_property( phandle_t ph, const char *name, const char *buf, int len )
282 {
283 if( !ph ) {
284 printk("set_property: NULL phandle\n");
285 return;
286 }
287 PUSH(pointer2cell(buf));
288 PUSH(len);
289 push_str( name );
290 PUSH_ph(ph);
291 fword("set-property");
292 }
293
294 void
set_int_property(phandle_t ph,const char * name,u32 val)295 set_int_property( phandle_t ph, const char *name, u32 val )
296 {
297 u32 swapped=__cpu_to_be32(val);
298 set_property( ph, name, (char*)&swapped, sizeof(swapped) );
299 }
300
301 char *
get_property(phandle_t ph,const char * name,int * retlen)302 get_property( phandle_t ph, const char *name, int *retlen )
303 {
304 int len;
305
306 if( retlen )
307 *retlen = -1;
308
309 push_str( name );
310 PUSH_ph( ph );
311 fword("get-package-property");
312 if( POP() )
313 return NULL;
314 len = POP();
315 if( retlen )
316 *retlen = len;
317 return (char*)cell2pointer(POP());
318 }
319
320 u32
get_int_property(phandle_t ph,const char * name,int * retlen)321 get_int_property( phandle_t ph, const char *name, int *retlen )
322 {
323 u32 *p;
324
325 if( !(p=(u32 *)get_property(ph, name, retlen)) )
326 return 0;
327 return __be32_to_cpu(*p);
328 }
329
330
331 /************************************************************************/
332 /* device selection / iteration */
333 /************************************************************************/
334
335 void
activate_dev(phandle_t ph)336 activate_dev( phandle_t ph )
337 {
338 PUSH_ph( ph );
339 fword("active-package!");
340 }
341
342 phandle_t
activate_device(const char * str)343 activate_device( const char *str )
344 {
345 phandle_t ph = find_dev( str );
346 activate_dev( ph );
347 return ph;
348 }
349
350 void
device_end(void)351 device_end( void )
352 {
353 fword("device-end");
354 }
355
356 phandle_t
get_cur_dev(void)357 get_cur_dev( void )
358 {
359 fword("active-package");
360 return POP_ph();
361 }
362
363 phandle_t
find_dev(const char * path)364 find_dev( const char *path )
365 {
366 phandle_t ret = 0;
367 push_str( path );
368 fword("(find-dev)");
369 if( POP() )
370 return POP_ph();
371 return ret;
372 }
373
374 char *
get_path_from_ph(phandle_t ph)375 get_path_from_ph( phandle_t ph )
376 {
377 PUSH(ph);
378 fword("get-package-path");
379 return pop_fstr_copy();
380 }
381
382 phandle_t
dt_iter_begin(void)383 dt_iter_begin( void )
384 {
385 fword("iterate-tree-begin");
386 return POP_ph();
387 }
388
389 phandle_t
dt_iterate(phandle_t last_tree)390 dt_iterate( phandle_t last_tree )
391 {
392 if( !last_tree )
393 return dt_iter_begin();
394
395 PUSH_ph( last_tree );
396 fword("iterate-tree");
397 return POP_ph();
398 }
399
400 phandle_t
dt_iterate_type(phandle_t last_tree,const char * type)401 dt_iterate_type( phandle_t last_tree, const char *type )
402 {
403 if( !last_tree )
404 last_tree = dt_iter_begin();
405
406 /* root node is never matched but we don't care about that */
407 while( (last_tree = dt_iterate(last_tree)) ) {
408 char *s = get_property( last_tree, "device_type", NULL );
409 if( s && !strcmp(type, s) )
410 break;
411 }
412 return last_tree;
413 }
414
415
416 /************************************************************************/
417 /* node methods */
418 /************************************************************************/
419
420 void
make_openable(int only_parents)421 make_openable( int only_parents )
422 {
423 phandle_t ph, save_ph = get_cur_dev();
424 PUSH_ph( save_ph );
425
426 for( ;; ) {
427 if( only_parents++ )
428 fword("parent");
429 if( !(ph=POP_ph()) )
430 break;
431 activate_dev( ph );
432 PUSH_ph( ph );
433 fword("is-open");
434 }
435 activate_dev( save_ph );
436 }
437
438 static void
call1_func(void)439 call1_func( void )
440 {
441 void (*func)(cell v);
442 func = (void*)cell2pointer(POP());
443
444 (*func)( POP() );
445 }
446
447
448 static void
add_methods(int flags,int size,const method_t * methods,int nmet)449 add_methods( int flags, int size, const method_t *methods, int nmet )
450 {
451 xt_t xt=0;
452 int i;
453
454 /* nodes might be matched multiple times */
455 if( find_package_method(methods[0].name, get_cur_dev()) )
456 return;
457
458 if( size ) {
459 PUSH( size );
460 fword("is-ibuf");
461 xt = POP_xt();
462 }
463
464 for( i=0; i<nmet; i++ ) {
465 /* null-name methods specify static initializers */
466 if( !methods[i].name ) {
467 typedef void (*initfunc)( void *p );
468 char *buf = NULL;
469 if( xt ) {
470 enterforth( xt );
471 buf = (char*)cell2pointer(POP());
472 }
473 (*(initfunc)methods[i].func)( buf );
474 continue;
475 }
476 if( !size )
477 bind_func( methods[i].name, methods[i].func );
478 else
479 bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func),
480 &call1_func );
481 }
482
483 if( flags & INSTALL_OPEN )
484 make_openable(0);
485 }
486
487 void
bind_node_methods(phandle_t ph,int flags,int size,const method_t * methods,int nmet)488 bind_node_methods(phandle_t ph, int flags, int size, const method_t *methods, int nmet)
489 {
490 phandle_t save_ph = get_cur_dev();
491
492 activate_dev(ph);
493 add_methods(flags, size, methods, nmet);
494 activate_dev( save_ph );
495 }
496
497 void
bind_node(int flags,int size,const char * const * paths,int npaths,const method_t * methods,int nmet)498 bind_node( int flags, int size, const char * const *paths, int npaths,
499 const method_t *methods, int nmet )
500 {
501 phandle_t save_ph = get_cur_dev();
502 int i;
503
504 for( i=0; i<npaths; i++ ) {
505 const char *name = paths[i];
506
507 /* type matching? */
508 if( *name == 'T' ) {
509 phandle_t ph = 0;
510 name++;
511 while( (ph=dt_iterate_type(ph, name)) ) {
512 activate_dev( ph );
513 add_methods( flags, size, methods, nmet );
514 }
515 continue;
516 }
517
518 /* path patching */
519 if( activate_device(name) )
520 add_methods( flags, size, methods, nmet );
521 else if( *name == '+' ) {
522 /* create node (and missing parents) */
523 if( !activate_device(++name) ) {
524 push_str( name );
525 fword("create-node");
526 }
527 add_methods( flags, size, methods, nmet );
528 }
529 }
530 activate_dev( save_ph );
531 }
532
533 phandle_t
bind_new_node(int flags,int size,const char * name,const method_t * methods,int nmet)534 bind_new_node( int flags, int size, const char *name,
535 const method_t *methods, int nmet )
536 {
537 phandle_t save_ph = get_cur_dev();
538 phandle_t new_ph;
539 /* create node */
540 push_str( name );
541 fword("create-node");
542 add_methods( flags, size, methods, nmet );
543 new_ph = get_cur_dev();
544
545 activate_dev( save_ph );
546 return new_ph;
547 }
548