filename | src/dcload.c |
changeset | 209:ff67a7b9aa17 |
prev | 183:5938ecc01dc8 |
next | 422:61a0598e07ff |
author | nkeynes |
date | Sat Jan 06 04:06:36 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Implement event queue. Fix pvr2 timing (yes, again). |
file | annotate | diff | log | raw |
1.1 --- a/src/dcload.c Thu Jul 06 22:44:39 2006 +00001.2 +++ b/src/dcload.c Sat Jan 06 04:06:36 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: dcload.c,v 1.5 2006-07-06 22:44:39 nkeynes Exp $1.6 + * $Id: dcload.c,v 1.6 2006-08-07 13:18:16 nkeynes Exp $1.7 *1.8 * DC-load syscall implementation.1.9 *1.10 @@ -48,40 +48,104 @@1.11 #define SYS_MAGIC_ADDR 0x8c0040041.12 #define SYSCALL_ADDR 0x8c0040081.14 -static gboolean dcload_allow_exit = FALSE;1.15 +static gboolean dcload_allow_unsafe = FALSE;1.17 -void dcload_set_allow_exit( gboolean allow )1.18 +void dcload_set_allow_unsafe( gboolean allow )1.19 {1.20 - dcload_allow_exit = allow;1.21 + dcload_allow_unsafe = allow;1.22 +}1.23 +1.24 +#define MAX_OPEN_FDS 161.25 +/**1.26 + * Mapping from emulator fd to real fd (so we can limit read/write1.27 + * to only fds we've explicitly granted access to).1.28 + */1.29 +int open_fds[MAX_OPEN_FDS];1.30 +1.31 +int dcload_alloc_fd()1.32 +{1.33 + int i;1.34 + for( i=0; i<MAX_OPEN_FDS; i++ ) {1.35 + if( open_fds[i] == -1 ) {1.36 + return i;1.37 + }1.38 + }1.39 + return -1;1.40 }1.42 void dcload_syscall( uint32_t syscall_id )1.43 {1.44 uint32_t syscall = sh4r.r[4];1.45 + int fd;1.46 switch( sh4r.r[4] ) {1.47 case SYS_READ:1.48 - if( sh4r.r[5] == 0 ) {1.49 + fd = sh4r.r[5];1.50 + if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {1.51 + sh4r.r[0] = -1;1.52 + } else {1.53 char *buf = mem_get_region( sh4r.r[6] );1.54 int length = sh4r.r[7];1.55 - sh4r.r[0] = read( 0, buf, length );1.56 + sh4r.r[0] = read( open_fds[fd], buf, length );1.57 + }1.58 + break;1.59 + case SYS_WRITE:1.60 + fd = sh4r.r[5];1.61 + if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {1.62 + sh4r.r[0] = -1;1.63 } else {1.64 + char *buf = mem_get_region( sh4r.r[6] );1.65 + int length = sh4r.r[7];1.66 + sh4r.r[0] = write( open_fds[fd], buf, length );1.67 + }1.68 + break;1.69 + case SYS_LSEEK:1.70 + fd = sh4r.r[5];1.71 + if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {1.72 + sh4r.r[0] = -1;1.73 + } else {1.74 + sh4r.r[0] = lseek( open_fds[fd], sh4r.r[6], sh4r.r[7] );1.75 + }1.76 + break;1.77 +1.78 +/* Secure access only */1.79 + case SYS_OPEN:1.80 + if( dcload_allow_unsafe ) {1.81 + fd = dcload_alloc_fd();1.82 + if( fd == -1 ) {1.83 + sh4r.r[0] = -1;1.84 + } else {1.85 + char *filename = mem_get_region( sh4r.r[5] );1.86 + int realfd = open( filename, sh4r.r[6] );1.87 + open_fds[fd] = realfd;1.88 + sh4r.r[0] = realfd;1.89 + }1.90 + } else {1.91 + ERROR( "Denying access to local filesystem" );1.92 sh4r.r[0] = -1;1.93 }1.94 break;1.95 - case SYS_WRITE:1.96 - if( sh4r.r[5] == 1 || sh4r.r[5] == 2 ) {1.97 - char *buf = mem_get_region( sh4r.r[6] );1.98 - int length = sh4r.r[7];1.99 - sh4r.r[0] = write( sh4r.r[5], buf, length );1.100 - } else {1.101 - sh4r.r[0] = -1;1.102 + case SYS_CLOSE:1.103 + if( dcload_allow_unsafe ) {1.104 + fd = sh4r.r[5];1.105 + if( fd < 0 || fd >= MAX_OPEN_FDS || open_fds[fd] == -1 ) {1.106 + sh4r.r[0] = -1;1.107 + } else {1.108 + if( open_fds[fd] > 2 ) {1.109 + sh4r.r[0] = close( open_fds[fd] );1.110 + } else {1.111 + /* Don't actually close real fds 0-2 */1.112 + sh4r.r[0] = 0;1.113 + }1.114 + open_fds[fd] = -1;1.115 + }1.116 }1.117 break;1.118 case SYS_EXIT:1.119 - if( dcload_allow_exit )1.120 + if( dcload_allow_unsafe ) {1.121 exit( sh4r.r[5] );1.122 - else1.123 + } else {1.124 dreamcast_stop();1.125 + }1.126 default:1.127 sh4r.r[0] = -1;1.128 }1.129 @@ -90,6 +154,10 @@1.131 void dcload_install()1.132 {1.133 + memset( &open_fds, -1, sizeof(open_fds) );1.134 + open_fds[0] = 0;1.135 + open_fds[1] = 1;1.136 + open_fds[2] = 2;1.137 syscall_add_hook_vector( 0xF0, SYSCALL_ADDR, dcload_syscall );1.138 sh4_write_long( SYS_MAGIC_ADDR, SYS_MAGIC );1.139 }
.