new fs stuff
[nestedvm.git] / src / org / ibex / nestedvm / Runtime.java
index fd2b985..bcbadd4 100644 (file)
@@ -86,6 +86,11 @@ public abstract class Runtime implements UsermodeConstants,Registers {
     final static int OPEN_MAX = 256;
     /** Table containing all open file descriptors. (Entries are null if the fd is not in use */
     FD[] fds  = new FD[OPEN_MAX];
+    
+    /** Pointer to a callback for the call_java syscall */
+    protected CallJavaCB callJavaCB;
+    public void setCallJavaCB(CallJavaCB callJavaCB) { this.callJavaCB = callJavaCB; }
+    public CallJavaCB getCallJavaCB() { return callJavaCB; }
         
     /** Temporary buffer for read/write operations */
     private byte[] _byteBuf = null;
@@ -189,6 +194,7 @@ public abstract class Runtime implements UsermodeConstants,Registers {
         <i>addr</i> INTO a java byte array <i>a</i> */
     public final void copyin(int addr, byte[] buf, int count) throws ReadFaultException {
         int x=0;
+        if(count == 0) return;
         if((addr&3)!=0) {
             int word = memRead(addr&~3);
             switch(addr&3) {
@@ -231,6 +237,7 @@ public abstract class Runtime implements UsermodeConstants,Registers {
         space at <i>addr</i> */
     public final void copyout(byte[] buf, int addr, int count) throws FaultException {
         int x=0;
+        if(count == 0) return;
         if((addr&3)!=0) {
             int word = memRead(addr&~3);
             switch(addr&3) {
@@ -542,6 +549,7 @@ public abstract class Runtime implements UsermodeConstants,Registers {
     /** Hook for subclasses to do their own startup */
     protected void _start() { /* noop */ }
     
+    // FEATURE: call() that accepts an Object[] array and automatically allocates strings/arrays/etc on the stack
     public final int call(String sym) throws CallException { return call(sym,0,0,0,0,0,0,0); }
     public final int call(String sym, int a0) throws CallException  { return call(sym,a0,0,0,0,0,0,0); }
     public final int call(String sym, int a0, int a1) throws CallException  { return call(sym,a0,a1,0,0,0,0,0); }
@@ -594,12 +602,6 @@ public abstract class Runtime implements UsermodeConstants,Registers {
         return cpustate.r[V1];
     }
     
-    // FEATURE: This is ugly - we should have some kind of way  to specify a callback rather than requiring subclassing
-    protected int callJava(int a, int b, int c, int d) {
-        System.err.println("WARNING: Default implementation of callJava() called with args " + toHex(a) + "," + toHex(b) + "," + toHex(c) + "," + toHex(d));
-        return 0;
-    }
-    
     /** Determines if the process can access <i>fileName</i>. The default implementation simply logs 
         the request and allows it */
     protected boolean allowFileAccess(String fileName, boolean write) {
@@ -626,6 +628,17 @@ public abstract class Runtime implements UsermodeConstants,Registers {
         fds[fdn] = null;        
         return true;
     }
+    
+    /** Duplicates the file descriptor <i>fdn</i> and returns the new fs */
+    public int dupFD(int fdn) {
+               int i;
+               if(fdn < 0 || fdn >= OPEN_MAX) return -1;
+               if(fds[fdn] == null) return -1;
+               for(i=0;i<OPEN_MAX;i++) if(fds[i] == null) break;
+        if(i==OPEN_MAX) return -1;
+        fds[i] = fds[fdn].dup();
+        return i;
+    }
 
     // FEATURE: These should be pulled in from UsermodeConstants but fcntl.h is hard to parse
     public static final int RD_ONLY = 0;
@@ -874,12 +887,19 @@ public abstract class Runtime implements UsermodeConstants,Registers {
     private int sys_getpid() { return getPid(); }
     protected int getPid() { return 1; }
     
+    public static interface CallJavaCB { public int call(int a, int b, int c, int d); }
+    
     private int sys_calljava(int a, int b, int c, int d) {
         if(state != RUNNING) throw new IllegalStateException("wound up calling sys_calljava while not in RUNNING");
-        state = CALLJAVA;
-        int ret = callJava(a,b,c,d);
-        state = RUNNING;
-        return ret;
+        if(callJavaCB != null) {
+            state = CALLJAVA;
+            int ret = callJavaCB.call(a,b,c,d);
+            state = RUNNING;
+            return ret;
+        } else {
+                       System.err.println("WARNING: calljava syscall invoked without a calljava callback set");
+                       return 0;
+        }
     }
         
     private int sys_pause() {
@@ -1143,9 +1163,17 @@ public abstract class Runtime implements UsermodeConstants,Registers {
         private final boolean executable; 
         public HostFStat(File f) {
             this.f = f;
-            String name = f.getName();
-            // FEATURE: This is ugly.. maybe we should do a file(1) type check
-            executable = name.endsWith(".mips") || name.endsWith(".sh");
+            boolean _executable = false;
+            // FEATURE: This might be too expensive
+            try {
+                FileInputStream fis = new FileInputStream(f);
+                switch(fis.read()) {
+                    case '\177': _executable = fis.read() == 'E' && fis.read() == 'L' && fis.read() == 'F'; break;
+                    case '#': _executable = fis.read() == '!';
+                }
+                fis.close();
+            } catch(IOException e) { /* ignore */ }
+            executable = _executable;
         }
         public int dev() { return 1; }
         public int inode() { return f.getName().hashCode() & 0xffff; }