mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Refactoring of the OpenBIOS source code, as discussed on the mailing list. The primary aim of this process is to try and arrange
the source files into a structure whereby it is easier to find the relationship between a forth package word and its C implementation, while also creating a libopenbios library into which more common code from the arch/ tree can eventually be moved. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@685 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
committed by
Mark Cave-Ayland
parent
0d5f749065
commit
dbf16392cc
522
libopenbios/bindings.c
Normal file
522
libopenbios/bindings.c
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* 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 "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "libc/string.h"
|
||||
#include "libc/stdlib.h"
|
||||
#include "libc/byteorder.h"
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* forth interface glue */
|
||||
/************************************************************************/
|
||||
|
||||
void
|
||||
push_str( const char *str )
|
||||
{
|
||||
PUSH( (ucell)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( (ucell)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( (cell)func );
|
||||
push_str( name );
|
||||
fword("is-xt-cfunc");
|
||||
}
|
||||
|
||||
xt_t
|
||||
bind_noname_func( void (*func)(void) )
|
||||
{
|
||||
PUSH( (ucell)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*)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((ucell)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*)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*)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*)POP();
|
||||
}
|
||||
(*(initfunc)methods[i].func)( buf );
|
||||
continue;
|
||||
}
|
||||
if( !size )
|
||||
bind_func( methods[i].name, methods[i].func );
|
||||
else
|
||||
bind_xtfunc( methods[i].name, xt, (ucell)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 );
|
||||
}
|
||||
|
||||
void
|
||||
bind_new_node( int flags, int size, const char *name,
|
||||
const method_t *methods, int nmet )
|
||||
{
|
||||
phandle_t save_ph = get_cur_dev();
|
||||
|
||||
/* create node */
|
||||
push_str( name );
|
||||
fword("create-node");
|
||||
add_methods( flags, size, methods, nmet );
|
||||
|
||||
activate_dev( save_ph );
|
||||
}
|
||||
Reference in New Issue
Block a user