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