Search
lxdream.org :: lxdream/src/dcload.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/dcload.c
changeset 736:a02d1475ccfd
prev671:a530ea88eebd
next1065:bc1cc0c54917
author nkeynes
date Mon Oct 06 01:05:12 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Move bundle/system paths into paths.c, install lxdreamrc into the bundle
(Fix OSX bundle missing default configuration)
view annotate diff log raw
     1 /**
     2  * $Id$
     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/sh4.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             dreamcast_shutdown();
   149             exit( sh4r.r[5] );
   150         } else {
   151             dreamcast_stop();
   152         }
   153     default:
   154         sh4r.r[0] = -1;
   155     }
   157 }
   159 void dcload_install() 
   160 {
   161     memset( &open_fds, -1, sizeof(open_fds) );
   162     open_fds[0] = 0;
   163     open_fds[1] = 1;
   164     open_fds[2] = 2;
   165     syscall_add_hook_vector( 0xF0, SYSCALL_ADDR, dcload_syscall );
   166     mem_write_long( SYS_MAGIC_ADDR, SYS_MAGIC );
   167 }
.