Author: arty
Date: Sun Sep 2 13:02:12 2007
New Revision: 28757
URL:
http://svn.reactos.org/svn/reactos?rev=28757&view=rev
Log:
Add interface generator for open firmware calls.
Added:
trunk/reactos/tools/ofw_interface/
trunk/reactos/tools/ofw_interface/calls.ofw
trunk/reactos/tools/ofw_interface/ofw_interface.cpp
trunk/reactos/tools/ofw_interface/ofw_interface.mak
Modified:
trunk/reactos/tools/tools.mak
Added: trunk/reactos/tools/ofw_interface/calls.ofw
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/ofw_interface/calls.…
==============================================================================
--- trunk/reactos/tools/ofw_interface/calls.ofw (added)
+++ trunk/reactos/tools/ofw_interface/calls.ofw Sun Sep 2 13:02:12 2007
@@ -1,0 +1,25 @@
+# Function Args Returns Types
+# Real OFW functions to proxy
+finddevice 1 1 char* int
+open 1 1 char* int
+getprop 4 1 int char* char*:arg3 int int
+write 3 1 int char*:arg2 int int
+read 3 1 int char*:arg2 int int
+exit 0 0
+child 1 1 int int
+peer 1 1 int int
+parent 1 1 int int
+seek 3 1 int int int int
+# MMU methods
+# claim (virt size align -- base)
+claim 3 1 int int int int
+# claim-mem (size align -- base)
+claim-mem 2 1 int int int
+# release (virt size --)
+release 2 0 int int
+package-to-path 3 1 int char*:arg2 int int
+# Declare the call-method BE function
++call-method 0 0
+# MMU Methods
+@phys2virt!translate 4 1 int int int int&0 int
+@virt2phys!translate 2 1 int int&1 int
Added: trunk/reactos/tools/ofw_interface/ofw_interface.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/ofw_interface/ofw_in…
==============================================================================
--- trunk/reactos/tools/ofw_interface/ofw_interface.cpp (added)
+++ trunk/reactos/tools/ofw_interface/ofw_interface.cpp Sun Sep 2 13:02:12 2007
@@ -1,0 +1,316 @@
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+class ofw_wrappers {
+public:
+ int base, ctindex, method_ctindex;
+ std::string functions;
+ std::string names;
+ std::string calltable;
+ std::string le_stubs;
+ std::string of_call;
+};
+
+class vartype {
+public:
+ vartype( const std::string &typestr ) {
+ size_t amp = typestr.find('&');
+ size_t col = typestr.find(':');
+ if( amp != std::string::npos ) {
+ if( col > amp && col != std::string::npos )
+ lit_value = typestr.substr(amp+1,col-amp+1);
+ else lit_value = typestr.substr(amp+1);
+ }
+ if( col != std::string::npos ) {
+ if( amp > col && amp != std::string::npos )
+ len = typestr.substr(col+1,amp-col+1);
+ else len = typestr.substr(col+1);
+ }
+
+ if( amp != std::string::npos && amp < col ) col = amp;
+ if( col == std::string::npos ) col = typestr.size();
+ c_type = typestr.substr(0,col);
+ }
+
+ vartype( const vartype &other )
+ : c_type(other.c_type),
+ len(other.len),
+ lit_value(other.lit_value) {
+ }
+
+ vartype &operator = ( const vartype &other ) {
+ c_type = other.c_type;
+ len = other.len;
+ lit_value = other.lit_value;
+ return *this;
+ }
+
+ std::string c_type;
+ std::string len;
+ std::string lit_value;
+};
+
+std::string uppercase( const std::string &toucase ) {
+ std::vector<char> ucase_work(toucase.size());
+ for( size_t i = 0; i < toucase.size(); i++ ) {
+ ucase_work[i] = toupper(toucase[i]);
+ }
+ return std::string(&ucase_work[0], toucase.size());
+}
+
+std::string clip_eol( std::string in, const std::string &eol_marks ) {
+ size_t found;
+ for( size_t i = 0; i < eol_marks.size(); i++ ) {
+ found = in.find( eol_marks[i] );
+ if( found != std::string::npos )
+ in = in.substr( 0, found );
+ }
+ return in;
+}
+
+int round_up( int x, int factor ) {
+ return (x + (factor - 1)) & ~(factor - 1);
+}
+
+void populate_definition( ofw_wrappers &wrapper, const std::string &line ) {
+ std::istringstream iss(line);
+ bool make_function = true, method_call = false, make_stub = true, comma;
+ std::string name, nametext, argtype, rettype;
+ std::vector<vartype> argtypes;
+ int args, rets, i, local_offset, total_stack, userarg_start = 0;
+ size_t f;
+ std::ostringstream function, ct_csource, le_stub, of_call;
+
+ iss >> name >> args >> rets;
+
+ if( !name.size() ) return;
+
+ if( (f = name.find('!')) != std::string::npos ) {
+ nametext = name.substr(f+1);
+ name = name.substr(0,f);
+ }
+ if( name[0] == '-' ) {
+ name = name.substr(1);
+ make_function = false;
+ }
+ if( name[0] == '+' ) {
+ name = name.substr(1);
+ make_stub = false;
+ }
+ if( name[0] == '@' ) {
+ name = name.substr(1);
+ method_call = true;
+ make_function = false;
+ }
+
+ if( !nametext.size() ) nametext = name;
+
+ for( i = 1; i < (int)name.size(); i++ )
+ if( name[i] == '-' ) name[i] = '_';
+
+ if( nametext == "call-method" )
+ wrapper.method_ctindex = wrapper.ctindex;
+
+ for( i = 0; i < args; i++ ) {
+ iss >> argtype;
+ argtypes.push_back(vartype(argtype));
+ }
+
+ if( method_call ) {
+ userarg_start = 1;
+ args += 2;
+ }
+
+ iss >> rettype;
+ if( !rettype.size() ) rettype = "void";
+
+ local_offset = (3 + rets + args) * 4;
+ total_stack = round_up(12 + local_offset, 16);
+
+ function << "asm_ofw_" << name << ":\n"
+ << "\t/* Reserve stack space */\n"
+ << "\tsubi %r1,%r1," << total_stack << "\n"
+ << "\t/* Store r8, r9, lr */\n"
+ << "\tstw %r8," << (local_offset + 0) <<
"(%r1)\n"
+ << "\tstw %r9," << (local_offset + 4) <<
"(%r1)\n"
+ << "\tmflr %r8\n"
+ << "\tstw %r8," << (local_offset + 8) <<
"(%r1)\n"
+ << "\t/* Get read name */\n"
+ << "\tlis %r8," << name << "_ofw_name@ha\n"
+ << "\taddi %r9,%r8," << name <<
"_ofw_name@l\n"
+ << "\tstw %r9,0(%r1)\n"
+ << "\t/* " << args << " arguments and "
<< rets << " return */\n"
+ << "\tli %r9," << args << "\n"
+ << "\tstw %r9,4(%r1)\n"
+ << "\tli %r9," << rets << "\n"
+ << "\tstw %r9,8(%r1)\n";
+
+ for( int i = 0; i < args; i++ )
+ function << "\tstw %r" << (i+3) << "," << (4
* (i + 3)) << "(%r1)\n";
+
+ function << "\t/* Load up the call address */\n"
+ << "\tlis %r10,ofw_call_addr@ha\n"
+ << "\tlwz %r9,ofw_call_addr@l(%r10)\n"
+ << "\tmtlr %r9\n"
+ << "\t/* Set argument */\n"
+ << "\tmr %r3,%r1\n"
+ << "\t/* Fire */\n"
+ << "\tblrl\n"
+ << "\tlwz %r3," << (local_offset - 4) <<
"(%r1)\n"
+ << "\t/* Restore registers */\n"
+ << "\tlwz %r8," << (local_offset + 8) <<
"(%r1)\n"
+ << "\tmtlr %r8\n"
+ << "\tlwz %r9," << (local_offset + 4) <<
"(%r1)\n"
+ << "\tlwz %r8," << (local_offset + 0) <<
"(%r1)\n"
+ << "\t/* Return */\n"
+ << "\taddi %r1,%r1," << total_stack << "\n"
+ << "\tblr\n";
+
+ if( method_call ) {
+ argtypes.insert(argtypes.begin(),vartype("int"));
+ argtypes.insert(argtypes.begin(),vartype("char*"));
+ }
+
+ le_stub << rettype << " ofw_" << name <<
"(";
+
+ comma = false;
+ for( i = userarg_start; i < args; i++ ) {
+ if( !argtypes[i].lit_value.size() ) {
+ if( !comma ) comma = true; else le_stub << ",";
+ le_stub << argtypes[i].c_type << " arg" << i;
+ }
+ }
+ le_stub << ")";
+ of_call << le_stub.str() << ";\n";
+
+ le_stub << " {\n";
+ if( rettype != "void" )
+ le_stub << "\t" << rettype << " ret;\n";
+
+ if( method_call ) {
+ le_stub << "\tchar arg0["
+ << round_up(nametext.size()+1,8)
+ << "] = \"" << nametext << "\";\n";
+ }
+
+ for( i = 0; i < args; i++ ) {
+ if( argtypes[i].lit_value.size() ) {
+ le_stub << "\t" << argtypes[i].c_type << "
arg" << i << " = "
+ << argtypes[i].lit_value << ";\n";
+ }
+ }
+
+ le_stub << "\t";
+ if( rettype != "void" ) le_stub << "ret = (" <<
rettype << ")";
+
+ le_stub << "ofproxy(" <<
+ (method_call ? (wrapper.method_ctindex * 4) : (wrapper.ctindex * 4));
+
+ for( i = 0; i < 6; i++ ) {
+ if( i < args ) le_stub << ",(void *)arg" << i;
+ else le_stub << ",NULL";
+ }
+
+ le_stub << ");\n";
+
+ if( rettype != "void" )
+ le_stub << "\treturn ret;\n";
+
+ le_stub << "}\n";
+
+ if( make_function ) wrapper.functions += function.str();
+ if( make_stub ) {
+ wrapper.le_stubs += le_stub.str();
+ wrapper.of_call += of_call.str();
+ }
+ if( !method_call ) {
+ wrapper.names += name + "_ofw_name:\n\t.asciz \"" + nametext +
"\"\n";
+ wrapper.calltable += std::string("\t.long asm_ofw_") + name + "\n";
+ wrapper.ctindex++;
+ }
+}
+
+int main( int argc, char **argv ) {
+ int status = 0;
+ std::ifstream in;
+ std::ofstream out, outcsource, outcheader;
+ std::string line;
+ const char *eol_marks = "#\r\n";
+ ofw_wrappers wrappers;
+
+ wrappers.base = 0xe00000;
+ wrappers.ctindex = 0;
+
+ if( argc < 5 ) {
+ fprintf( stderr, "%s [interface.ofw] [ofw.s] [le_stub.c] [le_stub.h]\n",
argv[0] );
+ return 1;
+ }
+
+ in.open( argv[1] );
+ if( !in ) {
+ fprintf( stderr, "can't open %s\n", argv[1] );
+ status = 1;
+ goto error;
+ }
+
+ out.open( argv[2] );
+ if( !out ) {
+ fprintf( stderr, "can't open %s\n", argv[2] );
+ status = 1;
+ goto error;
+ }
+
+ outcsource.open( argv[3] );
+ if( !outcsource ) {
+ fprintf( stderr, "can't open %s\n", argv[3] );
+ status = 1;
+ goto error;
+ }
+
+ outcheader.open( argv[4] );
+ if( !outcheader ) {
+ fprintf( stderr, "can't open %s\n", argv[4] );
+ status = 1;
+ goto error;
+ }
+
+ while( std::getline( in, line ) ) {
+ line = clip_eol( line, eol_marks );
+ if( line.size() ) populate_definition( wrappers, line );
+ }
+
+ out << "/* AUTOMATICALLY GENERATED BY ofw_interface */\n"
+ << "\t.section .text\n"
+ << "\t.align 4\n"
+ << "\t.globl _start\n"
+ << "\t.globl ofw_functions\n"
+ << "\t.globl ofw_call_addr\n"
+ << "ofw_call_addr:\n"
+ << "\t.long 0\n"
+ << "\n/* Function Wrappers */\n\n"
+ << wrappers.functions
+ << "\n/* Function Names */\n\n"
+ << wrappers.names
+ << "\n/* Function Call Table for Freeldr */\n\n"
+ << "\t.align 4\n"
+ << "ofw_functions:\n"
+ << wrappers.calltable
+ << "\n/* End */\n";
+
+ outcsource << "/* AUTOMATICALLY GENERATED BY ofw_interface */\n"
+ << "#include \"of.h\"\n"
+ << wrappers.le_stubs;
+
+ outcheader << "/* AUTOMATICALLY GENERATE BY ofw_interface */\n"
+ << "#ifndef _OFW_CALLS_H\n"
+ << "#define _OFW_CALLS_H\n"
+ << wrappers.of_call
+ << "#endif/*_OFW_CALLS_H*/\n";
+
+error:
+ return status;
+}
Added: trunk/reactos/tools/ofw_interface/ofw_interface.mak
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/ofw_interface/ofw_in…
==============================================================================
--- trunk/reactos/tools/ofw_interface/ofw_interface.mak (added)
+++ trunk/reactos/tools/ofw_interface/ofw_interface.mak Sun Sep 2 13:02:12 2007
@@ -1,0 +1,63 @@
+OFW_INTERFACE_BASE = $(TOOLS_BASE_)ofw_interface
+OFW_INTERFACE_BASE_ = $(OFW_INTERFACE_BASE)$(SEP)
+OFW_INTERFACE_INT = $(INTERMEDIATE_)$(OFW_INTERFACE_BASE)
+OFW_INTERFACE_INT_ = $(OFW_INTERFACE_INT)$(SEP)
+OFW_INTERFACE_OUT = $(OUTPUT_)$(OFW_INTERFACE_BASE)
+OFW_INTERFACE_OUT_ = $(OFW_INTERFACE_OUT)$(SEP)
+
+OFW_INTERFACE_OUTPUT = boot/freeldr/freeldr/arch/powerpc/ofw_calls.s
+OFW_INTERFACE_SOURCE = boot/freeldr/freeldr/arch/powerpc/ofw.c
+OFW_INTERFACE_HEADER = boot/freeldr/freeldr/include/of_call.h
+OFW_INTERFACE_INPUT = $(OFW_INTERFACE_BASE_)calls.ofw
+OFW_INTERFACE_SERVICE_FILES = \
+ $(OFW_INTERFACE_OUTPUT) \
+ $(OFW_INTERFACE_SOURCE) \
+ $(OFW_INTERFACE_HEADER)
+
+$(OFW_INTERFACE_INT): | $(TOOLS_INT)
+ $(ECHO_MKDIR)
+ ${mkdir} $@
+
+ifneq ($(INTERMEDIATE),$(OUTPUT))
+$(OFW_INTERFACE_OUT): | $(TOOLS_OUT)
+ $(ECHO_MKDIR)
+ ${mkdir} $@
+endif
+
+OFW_INTERFACE_TARGET = \
+ $(EXEPREFIX)$(OFW_INTERFACE_OUT_)ofw_interface$(EXEPOSTFIX)
+
+OFW_INTERFACE_SOURCES = $(addprefix $(OFW_INTERFACE_BASE_), \
+ ofw_interface.cpp \
+ )
+
+OFW_INTERFACE_OBJECTS = \
+ $(addprefix $(INTERMEDIATE_), $(OFW_INTERFACE_SOURCES:.cpp=.o))
+
+OFW_INTERFACE_HOST_CFLAGS = $(TOOLS_CFLAGS)
+
+OFW_INTERFACE_HOST_LFLAGS = $(TOOLS_LFLAGS)
+
+$(OFW_INTERFACE_TARGET): $(OFW_INTERFACE_OBJECTS) | $(OFW_INTERFACE_OUT)
+ $(ECHO_LD)
+ ${host_gpp} $(OFW_INTERFACE_OBJECTS) $(OFW_INTERFACE_HOST_LFLAGS) -o $@
+
+$(OFW_INTERFACE_INT_)ofw_interface.o: $(OFW_INTERFACE_BASE_)ofw_interface.cpp |
$(OFW_INTERFACE_INT)
+ $(ECHO_CC)
+ ${host_gpp} $(OFW_INTERFACE_HOST_CFLAGS) -c $< -o $@
+
+$(OFW_INTERFACE_SERVICE_FILES): $(OFW_INTERFACE_TARGET) $(OFW_INTERFACE_INPUT)
+ $(ECHO_OFW)
+ $(Q)$(OFW_INTERFACE_TARGET) \
+ $(OFW_INTERFACE_INPUT) \
+ $(OFW_INTERFACE_OUTPUT) \
+ $(OFW_INTERFACE_SOURCE) \
+ $(OFW_INTERFACE_HEADER)
+
+.PHONY: ofw_interface
+ofw_interface: $(OFW_INTERFACE_TARGET)
+
+.PHONY: ofw_interface_clean
+ofw_interface_clean:
+ -@$(rm) $(OFW_INTERFACE_TARGET) $(OFW_INTERFACE_OBJECTS) 2>$(NUL)
+clean: ofw_interface_clean
Modified: trunk/reactos/tools/tools.mak
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/tools.mak?rev=28757&…
==============================================================================
--- trunk/reactos/tools/tools.mak (original)
+++ trunk/reactos/tools/tools.mak Sun Sep 2 13:02:12 2007
@@ -47,6 +47,7 @@
include tools/cdmake/cdmake.mak
include tools/dbgprint/dbgprint.mak
include tools/gendib/gendib.mak
+include tools/ofw_interface/ofw_interface.mak
include tools/mkhive/mkhive.mak
include tools/nci/nci.mak
include tools/pefixup.mak