Added ability to load an arbitrary binary from an ethernet server and launch it
[akaros.git] / kern / src / syscall.c
index 0018394..0be42f8 100644 (file)
 #include <arch/timer.h>
 #include <ros/error.h>
 
+#include <rl8168.h>
 #include <string.h>
 #include <assert.h>
 #include <env.h>
 #include <pmap.h>
 #include <trap.h>
 #include <syscall.h>
+#include <kmalloc.h>
 
 void syscall_wrapper(struct Trapframe *tf)
 {
@@ -71,6 +73,97 @@ static ssize_t sys_serial_read(env_t* e, char *DANGEROUS buf, size_t len)
        #endif
 }
 
+static ssize_t sys_run_binary(env_t* e, void* binary_buf, void* arg, size_t len) {
+       uint8_t* new_binary = kmalloc(len, 0);
+       memcpy(new_binary, binary_buf, len);
+
+       env_t* env = env_create((uint8_t*)new_binary, len);
+       kfree(new_binary);
+       
+       e->env_status = ENV_RUNNABLE;
+       env_run(env);
+       return 0;
+}
+
+// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
+{ 
+       extern int eth_up;
+       
+       if (eth_up) {
+               
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               int total_sent = 0;
+               int just_sent = 0;
+               int cur_packet_len = 0;
+               while (total_sent != len) {
+                       cur_packet_len = ((len - total_sent) > MAX_PACKET_DATA) ? MAX_PACKET_DATA : (len - total_sent);
+                       char* wrap_buffer = packet_wrap(buf + total_sent, cur_packet_len);
+                       just_sent = send_frame(wrap_buffer, cur_packet_len + PACKET_HEADER_SIZE);
+                       
+                       if (just_sent < 0)
+                               return 0; // This should be an error code of its own
+                               
+                       if (wrap_buffer)
+                               kfree(wrap_buffer);
+                               
+                       total_sent += cur_packet_len;
+               }
+               
+               return (ssize_t)len;
+               
+       }
+       else
+               return -E_INVAL;
+}
+/*
+static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
+{ 
+       extern int eth_up;
+       
+       if (eth_up) {
+               
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               
+               return(send_frame(buf, len));
+       }
+       return -E_INVAL;
+}
+*/
+
+
+// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf, size_t len) 
+{
+       extern int eth_up;
+       
+       if (eth_up) {
+               extern int packet_waiting;
+               extern int packet_buffer_size;
+               extern char* packet_buffer;
+               extern char* packet_buffer_orig;
+               extern int packet_buffer_pos;
+                       
+               if (packet_waiting == 0)
+                       return 0;
+                       
+               int read_len = ((packet_buffer_pos + len) > packet_buffer_size) ? packet_buffer_size - packet_buffer_pos : len;
+
+               memcpy(buf, packet_buffer + packet_buffer_pos, read_len);
+       
+               packet_buffer_pos = packet_buffer_pos + read_len;
+       
+               if (packet_buffer_pos == packet_buffer_size) {
+                       kfree(packet_buffer_orig);
+                       packet_waiting = 0;
+               }
+       
+               return read_len;
+       }
+       else
+               return -E_INVAL;
+}
+
 // Invalidate the cache of this core
 static void sys_cache_invalidate(void)
 {
@@ -238,6 +331,13 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                        return sys_serial_write(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(e, (char *DANGEROUS)a1, (size_t)a2);
+               case SYS_run_binary:
+                       return sys_run_binary(e, (char *DANGEROUS)a1, 
+                                             (char* DANGEROUS)a2, (size_t)a3);
+               case SYS_eth_write:
+                       return sys_eth_write(e, (char *DANGEROUS)a1, (size_t)a2);
+               case SYS_eth_read:
+                       return sys_eth_read(e, (char *DANGEROUS)a1, (size_t)a2);        
                case SYS_cache_invalidate:
                        sys_cache_invalidate();
                        return 0;