Search
lxdream.org :: lxdream/src/dcload.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/dcload.c
changeset 502:c4ecae2b1b5e
prev422:61a0598e07ff
next561:533f6b478071
next586:2a3ba82cf243
author nkeynes
date Thu Nov 08 11:54:16 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Add sh4ptr_t type, start converting bare pointer refs to it
view annotate diff log raw
     1 /**
     2  * $Id: dcload.c,v 1.8 2007-11-08 11:54:16 nkeynes Exp $
     3  * 
     4  * DC-load syscall implementation.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <stdio.h>
    20 #include <unistd.h>
    21 #include <fcntl.h>
    23 #include "dream.h"
    24 #include "mem.h"
    25 #include "dreamcast.h"
    26 #include "syscall.h"
    27 #include "sh4/sh4core.h"
    29 #define SYS_READ 0
    30 #define SYS_WRITE 1
    31 #define SYS_OPEN 2
    32 #define SYS_CLOSE 3
    33 #define SYS_CREAT 4
    34 #define SYS_LINK 5
    35 #define SYS_UNLINK 6
    36 #define SYS_CHDIR 7
    37 #define SYS_CHMOD 8
    38 #define SYS_LSEEK 9
    39 #define SYS_FSTAT 10
    40 #define SYS_TIME 11
    41 #define SYS_STAT 12
    42 #define SYS_UTIME 13
    43 #define SYS_ASSIGNWRKMEM 14
    44 #define SYS_EXIT 15
    45 #define SYS_OPENDIR 16
    46 #define SYS_CLOSEDIR 17
    47 #define SYS_READDIR 18
    48 #define SYS_GETHOSTINFO 19
    50 #define SYS_MAGIC 0xDEADBEEF
    51 #define SYS_MAGIC_ADDR 0x8c004004
    52 #define SYSCALL_ADDR 0x8c004008
    54 static gboolean dcload_allow_unsafe = FALSE;
    56 void dcload_set_allow_unsafe( gboolean allow )
    57 {
    58     dcload_allow_unsafe = allow;
    59 }
    61 #define MAX_OPEN_FDS 16
    62 /**
    63  * Mapping from emulator fd to real fd (so we can limit read/write
    64  * to only fds we've explicitly granted access to).
    65  */
    66 int open_fds[MAX_OPEN_FDS];
    68 int dcload_alloc_fd() 
    69 {
    70     int i;
    71     for( i=0; i<MAX_OPEN_FDS; i++ ) {
    72 	if( open_fds[i] == -1 ) {
    73 	    return i;
    74 	}
    75     }
    76     return -1;
    77 }
    79 void dcload_syscall( uint32_t syscall_id ) 
    80 {
    81     // uint32_t syscall = sh4r.r[4];
    82     int fd;
    83     switch( sh4r.r[4] ) {
    84     case SYS_READ:
    85 	fd = sh4r.r[5];
    86 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
    87 	    sh4r.r[0] = -1;
    88 	} else {
    89 	    sh4ptr_t buf = mem_get_region( sh4r.r[6] );
    90 	    int length = sh4r.r[7];
    91 	    sh4r.r[0] = read( open_fds[fd], buf, length );
    92 	}
    93 	break;
    94     case SYS_WRITE:
    95 	fd = sh4r.r[5];
    96 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
    97 	    sh4r.r[0] = -1;
    98 	} else {
    99 	    sh4ptr_t buf = mem_get_region( sh4r.r[6] );
   100 	    int length = sh4r.r[7];
   101 	    sh4r.r[0] = write( open_fds[fd], buf, length );
   102 	}
   103 	break;
   104     case SYS_LSEEK:
   105 	fd = sh4r.r[5];
   106 	if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
   107 	    sh4r.r[0] = -1;
   108 	} else {
   109 	    sh4r.r[0] = lseek( open_fds[fd], sh4r.r[6], sh4r.r[7] );
   110 	}
   111 	break;
   113 /* Secure access only */
   114     case SYS_OPEN:
   115 	if( dcload_allow_unsafe ) {
   116 	    fd = dcload_alloc_fd();
   117 	    if( fd == -1 ) {
   118 		sh4r.r[0] = -1;
   119 	    } else {
   120 		char *filename = (char *)mem_get_region( sh4r.r[5] );
   121 		int realfd = open( filename, sh4r.r[6] );
   122 		open_fds[fd] = realfd;
   123 		sh4r.r[0] = realfd;
   124 	    }
   125 	} else {
   126 	    ERROR( "Denying access to local filesystem" );
   127 	    sh4r.r[0] = -1;
   128 	}
   129 	break;
   130     case SYS_CLOSE:
   131 	if( dcload_allow_unsafe ) {
   132 	    fd = sh4r.r[5];
   133 	    if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {
   134 		sh4r.r[0] = -1;
   135 	    } else {
   136 		if( open_fds[fd] > 2 ) {
   137 		    sh4r.r[0] = close( open_fds[fd] );
   138 		} else {
   139 		    /* Don't actually close real fds 0-2 */
   140 		    sh4r.r[0] = 0;
   141 		}
   142 		open_fds[fd] = -1;
   143 	    }
   144 	}
   145 	break;
   146     case SYS_EXIT:
   147 	if( dcload_allow_unsafe ) {
   148 	    exit( sh4r.r[5] );
   149 	} else {
   150 	    dreamcast_stop();
   151 	}
   152     default:
   153 	sh4r.r[0] = -1;
   154     }
   156 }
   158 void dcload_install() 
   159 {
   160     memset( &open_fds, -1, sizeof(open_fds) );
   161     open_fds[0] = 0;
   162     open_fds[1] = 1;
   163     open_fds[2] = 2;
   164     syscall_add_hook_vector( 0xF0, SYSCALL_ADDR, dcload_syscall );
   165     sh4_write_long( SYS_MAGIC_ADDR, SYS_MAGIC );
   166 }
.