Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / bindings.c
diff --git a/qemu/roms/openbios/libopenbios/bindings.c b/qemu/roms/openbios/libopenbios/bindings.c
new file mode 100644 (file)
index 0000000..5323421
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ *   Creation Date: <2003/11/24 12:30:18 samuel>
+ *   Time-stamp: <2004/01/07 19:37:38 samuel>
+ *
+ *     <bindings.c>
+ *
+ *     Forth bindings
+ *
+ *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   version 2
+ *
+ */
+
+#include "config.h"
+#include "libopenbios/bindings.h"
+#include "libc/string.h"
+#include "libc/stdlib.h"
+#include "libc/byteorder.h"
+
+
+/************************************************************************/
+/*     forth interface glue                                            */
+/************************************************************************/
+
+void
+push_str( const char *str )
+{
+       PUSH( pointer2cell(str) );
+       PUSH( str ? strlen(str) : 0 );
+}
+
+/* WARNING: sloooow - AVOID */
+cell
+feval( const char *str )
+{
+       push_str( str );
+       return eword("evaluate", 2);
+}
+
+cell
+_eword( const char *word, xt_t *cache_xt, int nargs )
+{
+       static xt_t catch_xt = 0;
+       cell ret = -1;
+
+       if( !catch_xt )
+               catch_xt = findword("catch");
+       if( !*cache_xt )
+               *cache_xt = findword( (char*)word );
+
+       if( *cache_xt ) {
+               PUSH_xt( *cache_xt );
+               enterforth( catch_xt );
+               if( (ret=POP()) )
+                       dstackcnt -= nargs;
+       }
+       return ret;
+}
+
+/* note: only the built-in dictionary is searched */
+int
+_fword( const char *word, xt_t *cache_xt )
+{
+       if( !*cache_xt )
+               *cache_xt = findword( (char*)word );
+
+       if( *cache_xt ) {
+               enterforth( *cache_xt );
+               return 0;
+       }
+       return -1;
+}
+
+int
+_selfword( const char *method, xt_t *cache_xt )
+{
+       if( !*cache_xt )
+               *cache_xt = find_ih_method( method, my_self() );
+       if( *cache_xt ) {
+               enterforth( *cache_xt );
+               return 0;
+       }
+       return -1;
+}
+
+int
+_parword( const char *method, xt_t *cache_xt )
+{
+       if( !*cache_xt )
+               *cache_xt = find_ih_method( method, my_parent() );
+       if( *cache_xt ) {
+               enterforth( *cache_xt );
+               return 0;
+       }
+       return -1;
+}
+
+void
+bind_func( const char *name, void (*func)(void) )
+{
+       PUSH( pointer2cell(func) );
+       push_str( name );
+       fword("is-cfunc");
+}
+
+void
+bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) )
+{
+       PUSH_xt( xt );
+       PUSH( arg );
+       PUSH( pointer2cell(func) );
+       push_str( name );
+       fword("is-xt-cfunc");
+}
+
+xt_t
+bind_noname_func( void (*func)(void) )
+{
+       PUSH( pointer2cell(func) );
+       fword("is-noname-cfunc");
+       return POP_xt();
+}
+
+void
+throw( int error )
+{
+       PUSH( error );
+       fword("throw");
+}
+
+
+/************************************************************************/
+/*     ihandle related                                                 */
+/************************************************************************/
+
+phandle_t
+ih_to_phandle( ihandle_t ih )
+{
+       PUSH_ih( ih );
+       fword("ihandle>phandle");
+       return POP_ph();
+}
+
+ihandle_t
+my_parent( void )
+{
+       fword("my-parent");
+       return POP_ih();
+}
+
+ihandle_t
+my_self( void )
+{
+       fword("my-self");
+       return POP_ih();
+}
+
+xt_t
+find_package_method( const char *method, phandle_t ph )
+{
+       push_str( method );
+       PUSH_ph( ph );
+       fword("find-method");
+       if( POP() )
+               return POP_xt();
+       return 0;
+}
+
+xt_t
+find_ih_method( const char *method, ihandle_t ih )
+{
+       return find_package_method( method, ih_to_phandle(ih) );
+}
+
+
+xt_t
+find_parent_method( const char *method )
+{
+       return find_ih_method( method, my_parent() );
+}
+
+void
+call_package( xt_t xt, ihandle_t ihandle )
+{
+       PUSH_xt( xt );
+       PUSH_ih( ihandle );
+       fword("call-package");
+}
+
+void
+call_parent( xt_t xt )
+{
+       PUSH_xt( xt );
+       fword("call-parent");
+}
+
+void
+call_parent_method( const char *method )
+{
+       push_str( method );
+       fword("$call-parent");
+}
+
+
+/************************************************************************/
+/*     open/close package/dev                                          */
+/************************************************************************/
+
+ihandle_t
+open_dev( const char *spec )
+{
+       push_str( spec );
+       fword("open-dev");
+       return POP_ih();
+}
+
+void
+close_dev( ihandle_t ih )
+{
+       PUSH_ih( ih );
+       fword("close-dev");
+}
+
+ihandle_t
+open_package( const char *argstr, phandle_t ph )
+{
+       push_str( argstr );
+       PUSH_ph( ph );
+       fword("open-package");
+       return POP_ih();
+}
+
+void
+close_package( ihandle_t ih )
+{
+       PUSH_ih( ih );
+       fword("close-package");
+}
+
+
+/************************************************************************/
+/*     ihandle arguments                                               */
+/************************************************************************/
+
+char *
+pop_fstr_copy( void )
+{
+       int len = POP();
+       char *str, *p = (char*)cell2pointer(POP());
+       if( !len )
+               return NULL;
+       str = malloc( len + 1 );
+        if( !str )
+                return NULL;
+       memcpy( str, p, len );
+       str[len] = 0;
+       return str;
+}
+
+char *
+my_args_copy( void )
+{
+       fword("my-args");
+       return pop_fstr_copy();
+}
+
+
+/************************************************************************/
+/*     properties                                                      */
+/************************************************************************/
+
+void
+set_property( phandle_t ph, const char *name, const char *buf, int len )
+{
+       if( !ph ) {
+               printk("set_property: NULL phandle\n");
+               return;
+       }
+       PUSH(pointer2cell(buf));
+       PUSH(len);
+       push_str( name );
+       PUSH_ph(ph);
+       fword("set-property");
+}
+
+void
+set_int_property( phandle_t ph, const char *name, u32 val )
+{
+       u32 swapped=__cpu_to_be32(val);
+       set_property( ph, name, (char*)&swapped, sizeof(swapped) );
+}
+
+char *
+get_property( phandle_t ph, const char *name, int *retlen )
+{
+       int len;
+
+       if( retlen )
+               *retlen = -1;
+
+       push_str( name );
+       PUSH_ph( ph );
+       fword("get-package-property");
+       if( POP() )
+               return NULL;
+       len = POP();
+       if( retlen )
+               *retlen = len;
+       return (char*)cell2pointer(POP());
+}
+
+u32
+get_int_property( phandle_t ph, const char *name, int *retlen )
+{
+       u32 *p;
+
+       if( !(p=(u32 *)get_property(ph, name, retlen)) )
+               return 0;
+       return __be32_to_cpu(*p);
+}
+
+
+/************************************************************************/
+/*     device selection / iteration                                    */
+/************************************************************************/
+
+void
+activate_dev( phandle_t ph )
+{
+       PUSH_ph( ph );
+       fword("active-package!");
+}
+
+phandle_t
+activate_device( const char *str )
+{
+       phandle_t ph = find_dev( str );
+       activate_dev( ph );
+       return ph;
+}
+
+void
+device_end( void )
+{
+       fword("device-end");
+}
+
+phandle_t
+get_cur_dev( void )
+{
+       fword("active-package");
+       return POP_ph();
+}
+
+phandle_t
+find_dev( const char *path )
+{
+       phandle_t ret = 0;
+       push_str( path );
+       fword("(find-dev)");
+       if( POP() )
+               return POP_ph();
+       return ret;
+}
+
+phandle_t
+dt_iter_begin( void )
+{
+       fword("iterate-tree-begin");
+       return POP_ph();
+}
+
+phandle_t
+dt_iterate( phandle_t last_tree )
+{
+        if( !last_tree )
+               return dt_iter_begin();
+
+        PUSH_ph( last_tree );
+       fword("iterate-tree");
+       return POP_ph();
+}
+
+phandle_t
+dt_iterate_type( phandle_t last_tree, const char *type )
+{
+        if( !last_tree )
+                last_tree = dt_iter_begin();
+
+       /* root node is never matched but we don't care about that */
+        while( (last_tree = dt_iterate(last_tree)) ) {
+                char *s = get_property( last_tree, "device_type", NULL );
+               if( s && !strcmp(type, s) )
+                       break;
+       }
+        return last_tree;
+}
+
+
+/************************************************************************/
+/*     node methods                                                    */
+/************************************************************************/
+
+void
+make_openable( int only_parents )
+{
+       phandle_t ph, save_ph = get_cur_dev();
+       PUSH_ph( save_ph );
+
+       for( ;; ) {
+               if( only_parents++ )
+                       fword("parent");
+               if( !(ph=POP_ph()) )
+                       break;
+               activate_dev( ph );
+               PUSH_ph( ph );
+               fword("is-open");
+       }
+       activate_dev( save_ph );
+}
+
+static void
+call1_func( void )
+{
+       void (*func)(cell v);
+       func = (void*)cell2pointer(POP());
+
+       (*func)( POP() );
+}
+
+
+static void
+add_methods( int flags, int size, const method_t *methods, int nmet )
+{
+       xt_t xt=0;
+       int i;
+
+       /* nodes might be matched multiple times */
+       if( find_package_method(methods[0].name, get_cur_dev()) )
+               return;
+
+       if( size ) {
+               PUSH( size );
+               fword("is-ibuf");
+               xt = POP_xt();
+       }
+
+       for( i=0; i<nmet; i++ ) {
+               /* null-name methods specify static initializers */
+               if( !methods[i].name ) {
+                       typedef void (*initfunc)( void *p );
+                       char *buf = NULL;
+                       if( xt ) {
+                               enterforth( xt );
+                               buf = (char*)cell2pointer(POP());
+                       }
+                       (*(initfunc)methods[i].func)( buf );
+                       continue;
+               }
+               if( !size )
+                       bind_func( methods[i].name, methods[i].func );
+               else
+                       bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func),
+                                    &call1_func );
+       }
+
+       if( flags & INSTALL_OPEN )
+               make_openable(0);
+}
+
+void
+bind_node( int flags, int size, const char * const *paths, int npaths,
+          const method_t *methods, int nmet )
+{
+       phandle_t save_ph = get_cur_dev();
+       int i;
+
+       for( i=0; i<npaths; i++ ) {
+               const char *name = paths[i];
+
+               /* type matching? */
+               if( *name == 'T' ) {
+                       phandle_t ph = 0;
+                       name++;
+                       while( (ph=dt_iterate_type(ph, name)) ) {
+                               activate_dev( ph );
+                               add_methods( flags, size, methods, nmet );
+                       }
+                       continue;
+               }
+
+               /* path patching */
+               if( activate_device(name) )
+                       add_methods( flags, size, methods, nmet );
+               else if( *name == '+' ) {
+                       /* create node (and missing parents) */
+                       if( !activate_device(++name) ) {
+                               push_str( name );
+                               fword("create-node");
+                       }
+                       add_methods( flags, size, methods, nmet );
+               }
+       }
+       activate_dev( save_ph );
+}
+
+phandle_t
+bind_new_node( int flags, int size, const char *name,
+          const method_t *methods, int nmet )
+{
+       phandle_t save_ph = get_cur_dev();
+       phandle_t new_ph;
+       /* create node */
+       push_str( name );
+       fword("create-node");
+       add_methods( flags, size, methods, nmet );
+    new_ph = get_cur_dev();
+
+       activate_dev( save_ph );
+       return new_ph;
+}