195 lines
5.0 KiB
C++
195 lines
5.0 KiB
C++
#include "memif.h"
|
|
#include "syscall.h"
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <algorithm>
|
|
|
|
struct sysret_t
|
|
{
|
|
reg_t result;
|
|
reg_t err;
|
|
};
|
|
|
|
sysret_t appsys_exit(htif_t* htif, memif_t* memif, reg_t code)
|
|
{
|
|
htif->stop(0); // coreid doesn't matter, stop shuts down everything
|
|
exit(code);
|
|
}
|
|
|
|
sysret_t appsys_open(htif_t* htif, memif_t* memif,
|
|
addr_t pname, reg_t len, reg_t flags, reg_t mode)
|
|
{
|
|
char name[len];
|
|
memif->read(pname,len,(uint8_t*)name);
|
|
return (sysret_t){open(name,flags,mode),errno};
|
|
}
|
|
|
|
sysret_t appsys_read(htif_t* htif, memif_t* memif,
|
|
reg_t fd, addr_t pbuf, reg_t len)
|
|
{
|
|
char* buf = (char*)malloc(len);
|
|
assert(buf);
|
|
sysret_t ret = {read(fd,buf,len),errno};
|
|
if(ret.result != (reg_t)-1)
|
|
memif->write(pbuf,ret.result,(uint8_t*)buf);
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_pread(htif_t* htif, memif_t* memif,
|
|
reg_t fd, addr_t pbuf, reg_t len, reg_t off)
|
|
{
|
|
char* buf = (char*)malloc(len);
|
|
assert(buf);
|
|
sysret_t ret = {pread(fd,buf,len,off),errno};
|
|
if(ret.result != (reg_t)-1)
|
|
memif->write(pbuf,ret.result,(uint8_t*)buf);
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_write(htif_t* htif, memif_t* memif,
|
|
reg_t fd, addr_t pbuf, reg_t len)
|
|
{
|
|
char* buf = (char*)malloc(len);
|
|
assert(buf);
|
|
memif->read(pbuf,len,(uint8_t*)buf);
|
|
sysret_t ret = {write(fd,buf,len),errno};
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_pwrite(htif_t* htif, memif_t* memif,
|
|
reg_t fd, addr_t pbuf, reg_t len, reg_t off)
|
|
{
|
|
char* buf = (char*)malloc(len);
|
|
assert(buf);
|
|
memif->read(pbuf,len,(uint8_t*)buf);
|
|
sysret_t ret = {pwrite(fd,buf,len,off),errno};
|
|
free(buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_close(htif_t* htif, memif_t* memif,
|
|
reg_t fd)
|
|
{
|
|
return (sysret_t){close(fd),errno};
|
|
}
|
|
|
|
sysret_t appsys_lseek(htif_t* htif, memif_t* memif,
|
|
reg_t fd, reg_t ptr, reg_t dir)
|
|
{
|
|
return (sysret_t){lseek(fd,ptr,dir),errno};
|
|
}
|
|
|
|
sysret_t appsys_fstat(htif_t* htif, memif_t* memif,
|
|
reg_t fd, addr_t pbuf)
|
|
{
|
|
struct stat buf;
|
|
sysret_t ret = {fstat(fd,&buf),errno};
|
|
if(ret.result != (reg_t)-1)
|
|
memif->write(pbuf,sizeof(buf),(uint8_t*)&buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_stat(htif_t* htif, memif_t* memif,
|
|
addr_t pname, reg_t len, addr_t pbuf)
|
|
{
|
|
char name[len];
|
|
memif->read(pname,len,(uint8_t*)name);
|
|
|
|
struct stat buf;
|
|
sysret_t ret = {stat(name,&buf),errno};
|
|
if(ret.result != (reg_t)-1)
|
|
memif->write(pbuf,sizeof(buf),(uint8_t*)&buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_lstat(htif_t* htif, memif_t* memif,
|
|
addr_t pname, reg_t len, addr_t pbuf)
|
|
{
|
|
char name[len];
|
|
memif->read(pname,len,(uint8_t*)name);
|
|
|
|
struct stat buf;
|
|
sysret_t ret = {lstat(name,&buf),errno};
|
|
if(ret.result != (reg_t)-1)
|
|
memif->write(pbuf,sizeof(buf),(uint8_t*)&buf);
|
|
return ret;
|
|
}
|
|
|
|
sysret_t appsys_link(htif_t* htif, memif_t* memif,
|
|
addr_t poname, reg_t olen, addr_t pnname, reg_t nlen)
|
|
{
|
|
char oname[olen],nname[nlen];
|
|
memif->read(poname,olen,(uint8_t*)oname);
|
|
memif->read(pnname,nlen,(uint8_t*)nname);
|
|
return (sysret_t){link(oname,nname),errno};
|
|
}
|
|
|
|
sysret_t appsys_unlink(htif_t* htif, memif_t* memif,
|
|
addr_t pname, reg_t len)
|
|
{
|
|
char name[len];
|
|
memif->read(pname,len,(uint8_t*)name);
|
|
return (sysret_t){unlink(name),errno};
|
|
}
|
|
|
|
sysret_t appsys_getmainvars(htif_t* htif, memif_t* memif,
|
|
addr_t pbuf, size_t limit)
|
|
{
|
|
extern char mainvars[0x1000];
|
|
extern long* mainvars_longp;
|
|
extern size_t mainvars_sz;
|
|
|
|
for (int i=1; i<=mainvars_longp[0]; i++)
|
|
mainvars_longp[i] += pbuf;
|
|
|
|
sysret_t ret;
|
|
if (mainvars_sz < limit)
|
|
ret = (sysret_t){0,0};
|
|
else
|
|
ret = (sysret_t){-1,ENOMEM};
|
|
|
|
memif->write(pbuf, std::min(mainvars_sz, limit), (uint8_t*)mainvars);
|
|
|
|
return ret;
|
|
}
|
|
|
|
typedef sysret_t (*syscall_t)(htif_t*,memif_t*,reg_t,reg_t,reg_t,reg_t);
|
|
|
|
void dispatch_syscall(htif_t* htif, memif_t* memif, addr_t mm)
|
|
{
|
|
reg_t magicmem[5];
|
|
memif->read(mm,sizeof(magicmem),(uint8_t*)magicmem);
|
|
|
|
void* syscall_table[256];
|
|
memset(syscall_table, 0, sizeof(syscall_table));
|
|
syscall_table[1] = (void*)appsys_exit;
|
|
syscall_table[3] = (void*)appsys_read;
|
|
syscall_table[4] = (void*)appsys_write;
|
|
syscall_table[5] = (void*)appsys_open;
|
|
syscall_table[6] = (void*)appsys_close;
|
|
syscall_table[28] = (void*)appsys_fstat;
|
|
syscall_table[19] = (void*)appsys_lseek;
|
|
syscall_table[18] = (void*)appsys_stat;
|
|
syscall_table[84] = (void*)appsys_lstat;
|
|
syscall_table[9] = (void*)appsys_link;
|
|
syscall_table[10] = (void*)appsys_unlink;
|
|
syscall_table[180] = (void*)appsys_pread;
|
|
syscall_table[181] = (void*)appsys_pwrite;
|
|
syscall_table[201] = (void*)appsys_getmainvars;
|
|
|
|
reg_t n = magicmem[0];
|
|
assert(n < sizeof(syscall_table)/sizeof(void*) && syscall_table[n]);
|
|
syscall_t p = (syscall_t)syscall_table[n];
|
|
|
|
sysret_t ret = p(htif,memif,magicmem[1],magicmem[2],magicmem[3],magicmem[4]);
|
|
|
|
memif->write(mm,sizeof(ret),(uint8_t*)&ret);
|
|
}
|