diff options
author | Robert de Bath <rdebath@poboxes.com> | 1996-05-18 21:26:34 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:32:28 +0200 |
commit | 0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (patch) | |
tree | f944db9d7b8152a1ea89e01d58b4f215ae11886c | |
download | dev86-0d2fbe9b1bd284ce2cad55be17e8f2c896031a25.tar.gz |
Import doselks/old
-rw-r--r-- | coroutine.c | 120 | ||||
-rw-r--r-- | doselks.c | 275 | ||||
-rw-r--r-- | doselks.h | 111 | ||||
-rw-r--r-- | p.c | 9 | ||||
-rw-r--r-- | syscalls.c | 494 | ||||
-rw-r--r-- | syscalls.h | 59 | ||||
-rw-r--r-- | t1.c | 11 | ||||
-rw-r--r-- | x.c | 368 |
8 files changed, 1447 insertions, 0 deletions
diff --git a/coroutine.c b/coroutine.c new file mode 100644 index 0000000..259b7c1 --- /dev/null +++ b/coroutine.c @@ -0,0 +1,120 @@ +#include <stdio.h> +#include "doselks.h" + +int in_process = 0; +int intr_pending = 0; +unsigned int current_ds, current_stack; +struct process * proc; + +/*************************************************************************** + * These two routines to make doselks and the user program into co-routines. + * + * The Server calls run_cpu which runs the client. + * The client then does an int $80 which calls elks_int. + * Elks_int then returns to the caller of run_cpu. + * + * The return value is the value of AX when the int $80 occured. + * On return ES is set to the DS of the client program. + * + * The instruction times are for the 286 + * + * If we were using a 486 then using mov's would be faster on the 286 they + * are the same speed but push/pop is smaller. + */ + +#asm + .data +bx_temp: ! Tempoary storage for BX. + .word 0 + .text ! The is where we store the current_ds in the _TEXT_ segment +cs_current_ds: ! for the elks_int routine + .word 0 +#endasm + +unsigned int run_cpu() +{ +#asm + mov ax,ds ; 2 + seg cs ! Store ds for return + mov [cs_current_ds],ax ; 5 + + cli ! We`re messing! ; 3 + test [_intr_pending],#$FFFF ! Last chance ... + jz skp + sti + xor ax,ax + ret +skp: + push bp ; 3 + push si ; 3 + push di ; 3 + mov [_current_stack],sp ; 5 + mov ax,#1 ; 2 + mov [_in_process],ax ; 5 + mov sp,[_proc] ; 5 + pop ax ! pppop ; 5 + pop [bx_temp] ; 5 + pop cx ; 5 + pop dx ; 5 + pop di ; 5 + pop si ; 5 + pop bp ; 5 + pop es ; 5 + mov bx,sp ! Switch to client stack ; 2 + mov ss,[bx+8] ! SS ; 5 + mov sp,[bx+10] ! SP ; 5 + push [bx+6] ! flags ; 5 + push [bx+4] ! CS ; 5 + push [bx+2] ! PC ; 5 + push [bx+0] ! DS ; 5 + mov bx,[bx_temp] ; 5 + pop ds ; 5 + iret ; 17 +#endasm +} + +unsigned int elks_int() +{ +#asm +.text + cli ; 3 + push ds ; 3 + push cs ; 3 + pop ds ; 5 + mov ds,[cs_current_ds] ; 5 + mov [bx_temp],bx ; 3 + mov bx,[_proc] ; 5 + add bx,#16 ; 2 + pop [bx+0] ! DS ; 5 + pop [bx+2] ! PC ; 5 + pop [bx+4] ! CS ; 5 + pop [bx+6] ! flags ; 5 + mov [bx+8],ss ! SS ; 3 + mov [bx+10],sp ! SP ; 3 + + mov sp,bx ! Ready for pppppush ; 2 + mov bx,ds ; 2 + mov ss,bx ; 2 + + push es ! wheeee ; 3 + push bp ; 3 + push si ; 3 + push di ; 3 + push dx ; 3 + push cx ; 3 + push [bx_temp] ; 5 + push ax ! This is the return value, handy ; 3 + + mov sp,[_current_stack] ; 5 + mov bx,#1 ; 2 + mov [_in_process],bx ; 5 + sti ! Finished F**** around with the stack ; 2 + + mov bx,[_proc] ; 5 + mov es,[bx+16] ! Set ES to the client`s DS ; 5 + pop di ; 5 + pop si ; 5 + pop bp ; 5 +#endasm +} + diff --git a/doselks.c b/doselks.c new file mode 100644 index 0000000..c2a77bb --- /dev/null +++ b/doselks.c @@ -0,0 +1,275 @@ +#include <stdio.h> +#include "doselks.h" + +#define DEBUGGER + +void build_stack(/* char ** argv, char ** envp */); + +long elks_int_orig; +union REGS regs; +int process_running; +int exit_code = 255; + +main(argc, argv, envp) +int argc; +char ** argv; +char ** envp; +{ + int rv; + + current_ds = __get_ds(); + if( argc <= 1 ) + { + printf("Usage: %s <8086_exe> [args]\n", argv[0]); + exit(exit_code); + } + + proc = calloc(sizeof(struct process), 1); + if( proc == 0 ) + printf("Unable to allocate memory for executable\n"); + else if( (rv = loadexe(argv[1])) >= 0 ) + { + proc->pid = 1; + proc->ppid = 1; + proc->pgrp = 1; + proc->umask = 022; + proc->next = proc; + + build_stack(argv+1, envp); + + elks_int_orig = __getvect(ELKSINT); + __setvect(ELKSINT, (long)elks_int); + +#ifndef MAKEME + run_executable(); +#else + dump_core(); +#endif + + __setvect(ELKSINT, elks_int_orig); + } + else + { + if( rv == -ENOMEM ) + printf("Unable to allocate memory for executable\n"); + else + printf("Cannot execute %s\n", argv[1]); + } + return(exit_code); +} + +int loadexe(fname) +char * fname; +{ + char bbuf[1024]; + int i, fd; + unsigned int ssize, size; + unsigned destseg; + struct elks_exec_hdr mh; + + if( ( fd = open(fname, O_RDONLY|O_BINARY) ) < 0 ) + { + return -ENOEXEC; + } + + /* Load the elks binary image and set it up in a suitable + * segment. Load CS and DS/SS according to image type. + */ + + if( read(fd, &mh,sizeof(mh))!=sizeof(mh) + || mh.hlen!=EXEC_HEADER_SIZE + || (mh.type!=ELKS_COMBID&&mh.type!=ELKS_SPLITID) + ) + { + close(fd); + return -ENOEXEC; + } + + size = ((mh.chmem+0xF) >> 4); + + if(mh.type==ELKS_COMBID) + ssize = mh.tseg+mh.dseg; + else + { + ssize = mh.tseg; + size += ((mh.tseg+0xF) >> 4); + } + + destseg = __segalloc(size); /* Allocate paragraphs */ + if( destseg == 0 ) + { + close(fd); + return -ENOMEM; + } + +#ifdef DEBUGGER + fprintf(stderr,"Executable - %s. tseg=0x%04lx dseg=0x%04lx bss=0x%04lx chmem=0x%04lx @ %04x\n", + mh.type==ELKS_COMBID?"(impure)":"Sep I/D", + mh.tseg,mh.dseg,mh.bseg,mh.chmem,destseg); +#endif + + proc->memory = destseg; + proc->memsize = size; + proc->cs = destseg; + + for(size=0; size<ssize; ) + { + i = sizeof(bbuf); if( i>ssize-size ) i=ssize-size; + + if(read(fd,bbuf,i)!=i) + { + close(fd); + __segfree(destseg); + return -ENOEXEC; + } + + __movedata(current_ds, (unsigned)bbuf, destseg, size, i); + size += i; + } + + if(mh.type==ELKS_SPLITID) + { + ssize = mh.dseg; + + destseg += ((mh.tseg+0xF) >> 4); + for(size=0; size<ssize; ) + { + i = sizeof(bbuf); if( i>ssize-size ) i=ssize-size; + + if(read(fd,bbuf,i)!=i) + { + close(fd); + __segfree(destseg); + return -ENOEXEC; + } + + __movedata(current_ds, (int)bbuf, destseg, size, i); + size += i; + } + } + close(fd); + + /* Zap the bss */ + ssize = size + mh.bseg; + memset(bbuf, '\0', 1024); + while(ssize > size) + { + i = sizeof(bbuf); if( i>ssize-size ) i=ssize-size; + __movedata(current_ds, (int)bbuf, destseg, size, i); + size += i; + } + /* + * Load the VM86 registers + */ + + /* proc->cs= Done above; */ + + proc->ds=destseg; + proc->ss=destseg; /* Same as DS */ + + proc->es=0; /* This will be preserved */ + proc->sp=mh.chmem; /* Args stacked later */ + proc->pc=0; /* Run from 0 */ + + /* + * Loaded + */ + + return 0; +} + +void +build_stack(argv, envp) +char ** argv; char ** envp; +{ + char buffer[1024]; + + char **p; + int argv_len=0, argv_count=0; + int envp_len=0, envp_count=0; + int stack_bytes; + unsigned short * pip; + char * pcp; + + /* How much space for argv */ + if(argv) for(p=argv; *p; p++) + { + argv_count++; argv_len += strlen(*p)+1; + } + + /* How much space for envp */ + if(envp) for(p=envp; *p; p++) + { + envp_count++; envp_len += strlen(*p)+1; + } + + /* tot it all up */ + stack_bytes = 2 /* argc */ + + argv_count * 2 + 2 /* argv */ + + argv_len + + envp_count * 2 + 2 /* envp */ + + envp_len; + + if( stack_bytes > sizeof(buffer)-2 ) + { + printf("Environment too large\n"); + exit(exit_code); + } + /* Allocate it */ + proc->sp -= stack_bytes; + +#ifdef DEBUGGER + printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n", + argv_count, argv_len, envp_count, envp_len, stack_bytes); +#endif + + /* Now build the data */ + pip=(unsigned short *) buffer; + pcp=buffer+sizeof(unsigned short *)*(1+argv_count+1+envp_count+1); + + *pip++ = argv_count; + for(p=argv; *p; p++) + { + *pip++ = (pcp-buffer)+proc->sp; + strcpy(pcp, *p); + pcp += strlen(*p)+1; + } + *pip++ = 0; + + for(p=envp; *p; p++) + { + *pip++ = (pcp-buffer)+proc->sp; + strcpy(pcp, *p); + pcp += strlen(*p)+1; + } + *pip++ = 0; + __movedata(current_ds, (unsigned)buffer, + proc->ds, proc->sp, stack_bytes); +} + +/***************************************************************************/ + +dump_core() +{ + char bbuf[1024]; + int i, fd; + unsigned destseg; + printf("Dumping core\n"); + + if( ( fd = open("core", O_WRONLY|O_BINARY|O_CREAT|O_TRUNC) ) < 0 ) + { + return -1; + } + + destseg = proc->memory; + + for(i=0; i<(proc->memsize+63)/64; i++) + { + __movedata( destseg+i*64, 0, current_ds, (unsigned)bbuf, 1024); + if( write(fd, bbuf, 1024) < 0 ) + printf("FAIL 7\n"); + } + + close(fd); +} + diff --git a/doselks.h b/doselks.h new file mode 100644 index 0000000..6ea67eb --- /dev/null +++ b/doselks.h @@ -0,0 +1,111 @@ + +#include <ctype.h> +#include <dos.h> +#include <malloc.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/wait.h> +#include <sys/resource.h> +#include <sys/stat.h> + +/* Function return vals */ + +extern unsigned int elks_int(); +extern unsigned int run_cpu(); + +/* Elks binary formats */ + +#define EXEC_HEADER_SIZE 32 + +struct elks_exec_hdr +{ + unsigned long type; +#define ELKS_COMBID 0x04100301L +#define ELKS_SPLITID 0x04200301L + unsigned long hlen; + unsigned long tseg; + unsigned long dseg; + unsigned long bseg; + unsigned long unused; + unsigned long chmem; + unsigned long unused2; +}; + +/* Elks cpu structure. */ + +struct fd_ref { + int ftype; + union { + int i; + FILE * f; + } fd; +} ; + +struct segment { + unsigned int seg; + unsigned int size; + int ref_count; +}; + +struct process +{ + unsigned int ax; /* NOTE The order of this is _closely_ related to */ + unsigned int bx; /* the coroutine assembler */ + unsigned int cx; + unsigned int dx; + unsigned int di; + unsigned int si; + unsigned int bp; + unsigned int es; + + unsigned int ds; /* start +16 +0 */ + unsigned int pc; /* start +16 +2 */ + unsigned int cs; /* start +16 +4 */ + unsigned int flgs; /* start +16 +6 */ + unsigned int ss; /* start +16 +8 */ + unsigned int sp; /* start +16 +10 */ + + /* From here down only accessed from C */ + int pending_op; + struct process * next; + + struct segment * text_seg; + struct segment * data_seg; + + int pid; + int ppid; + int pgrp; + int umask; + int uid; + int gid; + int euid; + int egid; + int suid; + int sgid; + long ignmask, trpmask; + int sigtrap; + + struct fd_ref fds[20]; + + struct rusage ruse; +}; + +extern struct process * proc; +extern unsigned int current_ds, current_stack; +extern int in_process; +extern int process_running; +extern int intr_pending; + +/* Elks syscall interface */ + +#define ELKSINT 0x80 +typedef int (*Scallp)( /* int, int, int */ ); +extern Scallp syscalltab[]; + +/******************************************************************************/ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + @@ -0,0 +1,9 @@ + +main(argc, argv) +int argc; +char ** argv; +{ + printf("=%d\n", argc); + printf("'%s'\n", argv[0]); + printf("'%s'\n", argv[1]); +} diff --git a/syscalls.c b/syscalls.c new file mode 100644 index 0000000..1300798 --- /dev/null +++ b/syscalls.c @@ -0,0 +1,494 @@ +#include <stdio.h> +#include "doselks.h" +#include "syscalls.h" + +/***************************************************************************/ + +/* Need to use stdio for CR<->NL translation */ +#define MAX_FD 20 +FILE * tty_file[MAX_FD] = {stdin, stdout, stderr}; + +int nextpid = 2; +int proc_one = 1; + +/***************************************************************************/ + +#define sys_exit elks_exit +elks_exit(wait_stat) +int wait_stat; +{ + struct process * cur; + int x; + + if(wait_stat & 0x80) dump_core(); + + /* save wait_stat */ + proc->ax = wait_stat; + if(proc->pid == 1) proc_one = 0; + + process_running--; + __segfree(proc->memory); + + for(cur=proc->next; cur!=proc; cur=cur->next) + if(cur->ppid == proc->pid) + cur->ppid = 1; + + return 0; +} + +#define sys_fork elks_fork +elks_fork(bx, cx, dx) +int bx, cx, dx; +{ + unsigned int size, i; + struct process * newproc; + + if(nextpid<0) return -EINVAL; /* TODO: max 32k forks */ + + newproc = calloc(sizeof(struct process), 1); + if( newproc == 0 ) return -ENOMEM; + + /* TODO: Fork only needs to dup DS */ + + proc->pending_op = 0; + *newproc = *proc; + newproc->ppid = newproc->pid; + newproc->memory = __segalloc(proc->memsize); + + if( newproc->memory == 0 ) + { + free(newproc); + return -ENOMEM; + } + + newproc->ss = newproc->ss-newproc->cs + newproc->memory; + newproc->ds = newproc->ds-newproc->cs + newproc->memory; + newproc->cs = newproc->memory; + + newproc->pid = nextpid++; + + /* Duplicate memory */ + for(i=0; i<newproc->memsize; i+=size ) + { + size = 0xFFF; if(size > newproc->memsize-i) size = newproc->memsize-i; + + __movedata(proc->memory+i, 0, newproc->memory+i, 0, size*16); + } + + proc->ax = newproc->pid; + newproc->ax = 0; + proc->next = newproc; + process_running++; + /* proc = newproc; */ + + return newproc->pid; +} + +struct process * +get_zombie(ppid, pid) +int ppid, pid; +{ + struct process * prev, * cur, *running=0; + /* Process group, not defined */ + if( pid < -1 ) return 0; + if( pid == 0 ) pid = -1; + + for(prev=proc, cur=proc->next; cur!=proc; prev=cur, cur=cur->next) + { + if(cur->ppid == ppid && (pid == -1 || cur->pid == pid)) + { + if(cur->pending_op != 1) + { + running = cur; + continue; + } + prev->next = cur->next; + cur->next = 0; + return cur; + } + } + return running; +} + +#define sys_wait4 elks_wait4 +elks_wait4(bx, cx, dx, di, si) +int bx, cx, dx, di, si; +{ + struct process * cur; + int cpid; + + cur = get_zombie(proc->pid, bx); + if( cur == 0 ) return -ECHILD; + + if( cur->pending_op != 1) + { + if( dx & WNOHANG ) + return 0; + else + return -EINTR; + } + + cpid = cur->pid; + if( cx ) __doke_es(cx, cur->ax); + if( di ) + __movedata(current_ds, (unsigned)&(cur->ruse), + proc->ds, di, sizeof(struct rusage)); + free(cur); + return cpid; +} + +#define sys_exec elks_exec +int elks_exec(bx, cx, dx) +int bx, cx, dx; +{ + struct process oldproc; + char fname[128]; + int ax; + + oldproc = *proc; + __strnget_es(fname, bx, sizeof(fname)-1); + fname[sizeof(fname)-1] = '\0'; + + if( (ax=loadexe(fname)) != 0 ) + { + return ax; + *proc = oldproc; + } + + __movedata(oldproc.ds, cx, proc->ds, proc->sp-dx, dx); + + /* + Fudge pointers. + */ + proc->sp -= dx; + + /* Args */ + ax = proc->sp + 2; + __set_es(proc->ds); + while(__deek_es(ax) != 0 ) + __doke_es(ax, __deek_es(ax)-dx), ax+=2; + + /* env */ + ax+=2; + while(__deek_es(ax) != 0 ) + __doke_es(ax, __deek_es(ax)-dx), ax+=2; + + __segfree(oldproc.memory); + return 0; +} + +#define sys_read elks_read +int elks_read(bx, cx, dx) +int bx, cx, dx; +{ + register int ch, rv=0; + if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; + do + { + ch = fgetc(tty_file[bx]); + if( ch == EOF ) break; + __poke_es(cx++, ch); + rv++; + } + while(--dx > 0 && stdio_pending(tty_file[bx])); + + return rv; +} + +#define sys_write elks_write +int elks_write(bx, cx, dx) +unsigned int bx, cx, dx; +{ + char ch[2]; + register unsigned int i; + if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; + + for(i=dx; i>0; i--) + { + if( fputc(__peek_es(cx++), tty_file[bx]) == EOF ) + return -1; + } + fflush(tty_file[bx]); + return dx; +} + +#define sys_open elks_open +int elks_open(bx, cx, dx) +{ + char fname[128]; + int i; + char *mode = ""; + + __strnget_es(fname, bx, sizeof(fname)-1); + fname[sizeof(fname)-1] = '\0'; + + for(i=0; i<MAX_FD; i++) + { + if(tty_file[i] == 0) break; + } + if( i >= MAX_FD ) return -EMFILE; + + /* Translate the mode; more or less */ + switch(cx&O_ACCMODE) + { + case O_RDONLY: + mode="r"; + break; + case O_WRONLY: + if( cx&O_APPEND ) mode="a"; + else if( cx&O_TRUNC ) mode="w"; + else mode="r+"; + break; + case O_RDWR: + if( cx&O_APPEND ) mode="a+"; + else if( cx&O_TRUNC ) mode="w+"; + else mode="r+"; + break; + } + + if( ( tty_file[i] = fopen(fname, mode) ) == 0 ) + { + if( errno == 0 ) return -ENOENT; + return -errno; + } + return i; +} + +#define sys_close elks_close +int elks_close(bx, cx, dx) +{ + if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; + fclose(tty_file[bx]); + tty_file[bx] = 0; + return 0; +} + +#define sys_lseek elks_lseek +int elks_lseek(bx, cx, dx) +{ + long l; + if( bx<0 || bx>MAX_FD || tty_file[bx] == 0 ) return -EBADF; + + __movedata(proc->ds, cx, current_ds, &l, 4); + + if( fseek(tty_file[bx], l, dx) < 0 ) return -ESPIPE; + + l = ftell(tty_file[bx]); + __movedata(current_ds, &l, proc->ds, cx, 4); + return 0; +} + +#define sys_brk elks_brk +int elks_brk(bx, cx, dx) +{ + /* For the moment we don't care; libc does enough */ + return 0; +} + +#define sys_getpid elks_getpid +int elks_getpid(bx, cx, dx) +{ + __doke_es(bx, proc->ppid); + return proc->pid; +} + +#define sys_getuid elks_getuid +int elks_getuid(bx, cx, dx) +{ + __doke_es(bx, proc->euid); + return proc->uid; +} + +#define sys_getgid elks_getgid +int elks_getgid(bx, cx, dx) +{ + __doke_es(bx, proc->egid); + return proc->gid; +} + +#define sys_setuid elks_setuid +int elks_setuid(bx, cx, dx) +{ + if( proc->euid == 0 + || proc->uid == bx || proc->euid == bx || proc->suid == bx) + { + if( proc->euid == 0 ) + proc->suid = proc->uid = bx; + proc->euid = bx; + } + else + return -EPERM; +} + +#define sys_setgid elks_setgid +int elks_setgid(bx, cx, dx) +{ + if( proc->euid == 0 + || proc->gid == bx || proc->egid == bx || proc->sgid == bx) + { + if( proc->euid == 0 ) + proc->sgid = proc->gid = bx; + proc->egid = bx; + } + else + return -EPERM; +} + +#define sys_umask elks_umask +int elks_umask(bx, cx, dx) +{ + cx= proc->umask; + proc->umask = (bx&0777); + return cx; +} + +void sig_trap(signo) +int signo; +{ + proc->sp -= 2; + __doke_es(proc->sp, signo); + proc->sp -= 2; + __doke_es(proc->sp, proc->pc); + proc->pc = proc->sigtrap; +} + +#define sys_signal elks_signal +int elks_signal(bx,cx,dx) +{ + int rv; + if( bx < 0 || bx >= NSIG ) return -EINVAL; + if( bx == SIGSTOP || bx == SIGKILL ) return 0; + + proc->trpmask &= ~(1L<<bx); + proc->ignmask &= ~(1L<<bx); + + if( cx == 0 ) /* Default */; + else if( cx == 1 ) proc->ignmask |= (1L<<bx); + else + { + proc->trpmask |= (1L<<bx); + proc->sigtrap = cx; + } + + return 0; +} + +#define sys_lstat elks_stat +#define sys_stat elks_stat +int elks_stat(bx,cx,dx) +{ + struct stat ms; + char fnamebuf[65]; + char dtabuf[128]; /* I think this only needs 32 bytes ... but ... */ + int v; + long ttime, tdate; + + __strnget_es(fnamebuf, bx, sizeof(fnamebuf)-1); + fnamebuf[64] = '\0'; + + v = __dos_stat(fnamebuf, dtabuf); + if( v < 0 ) return -ENOENT; + + ms.st_dev= *dtabuf; + ms.st_ino= 0; + ms.st_mode= ((dtabuf[0x15]&0x1)?0555:0777); /* + File or directory */ + if (dtabuf[0x15]&0x10) + ms.st_mode |= S_IFDIR; + else + ms.st_mode |= S_IFREG; + ms.st_nlink= 1; + ms.st_uid= 0; + ms.st_gid= 0; + ms.st_rdev= 0; + ms.st_size= *(long*)(dtabuf+0x1A); + + ttime = *((unsigned short*)(dtabuf+0x16)); + ttime = ( ttime &0x1F) * 2 + + ((ttime>>5) &0x2F) * 60 + + ((ttime>>11) &0x1F) * 3600L; + +/* FIXME: This needs a julian day calculator .. */ + tdate = *((unsigned short*)(dtabuf+0x18)); + tdate = ((tdate) &0x1F) -32 + + ((tdate>>5) &0x0F) * 31 + + ((tdate>>9) &0x7F) * (31*12); + + ms.st_mtime= tdate*86400L + ttime; + ms.st_atime= ms.st_mtime; + ms.st_ctime= ms.st_mtime; + + /* copy &ms -> es:cx */ + __movedata(current_ds, &ms, proc->ds, cx, sizeof(struct stat)); + + return 0; +} + +/***************************************************************************/ + +#define sys_enosys elks_enosys +int elks_enosys(bx, cx, dx) +int bx, cx, dx; +{ + printf("Unimplemented syscall(%d,0x%04x,0x%04x,0x%04x)\n", + proc->ax,proc->bx,proc->cx,proc->dx); + return -ENOSYS; +} + +#include "defn_tab.v" + +Scallp syscalltab[] = { +#include "call_tab.v" + elks_enosys +}; + +FILE * error; +run_executable() +{ + + register unsigned int r_ax; + register Scallp ptr; + process_running=1; + + error = fopen("errlog", "w"); + + do + { + if( proc->pending_op == 0 ) + { + fprintf(error, "Run %d AX=%-4d proc =%04x IP=%04x...", + proc->pid, proc->ax, proc, proc->pc); fflush(error); + proc->pending_op = run_cpu(); + } + if( r_ax = proc->pending_op ) + { + if( r_ax >= sizeof(syscalltab)/sizeof(Scallp) ) + r_ax = 0; + + fprintf(error, "%d: Call_%d(%04x, %04x, %04x) -> ", + proc->pid, r_ax, proc->bx, proc->cx, proc->dx); + fflush(error); + + if( r_ax == 1 ) + (void) elks_exit(proc->bx << 8); + else + { + __set_es(proc->ds); + if( (proc->ax = (*syscalltab[r_ax])(proc->bx, proc->cx, proc->dx, + proc->di, proc->si)) + != (unsigned) -EINTR ) + { + fprintf(error, "%d\n", proc->ax); + fflush(error); + proc->pending_op = 0; + continue; + } + } + fprintf(error, "%d\n", proc->ax); + fflush(error); + } + intr_pending = 0; /* FIXME: deal with */ + do { proc = proc->next; } while(proc->pending_op==1 && process_running); + } + while(process_running); +} + diff --git a/syscalls.h b/syscalls.h new file mode 100644 index 0000000..90c7a99 --- /dev/null +++ b/syscalls.h @@ -0,0 +1,59 @@ +extern int sys_exit __P((int, int, int)); +extern int sys_vfork __P((int, int, int)); +extern int sys_read __P((int, int, int)); +extern int sys_write __P((int, int, int)); +extern int sys_open __P((int, int, int)); +extern int sys_close __P((int, int, int)); +extern int sys_wait __P((int, int, int)); +extern int sys_creat __P((int, int, int)); +extern int sys_link __P((int, int, int)); +extern int sys_unlink __P((int, int, int)); +extern int sys_waitpid __P((int, int, int)); +extern int sys_chdir __P((int, int, int)); +extern int sys_time __P((int, int, int)); +extern int sys_mknod __P((int, int, int)); +extern int sys_chmod __P((int, int, int)); +extern int sys_chown __P((int, int, int)); +extern int sys_brk __P((int, int, int)); +extern int sys_stat __P((int, int, int)); +extern int sys_lseek __P((int, int, int)); +extern int sys_getpid __P((int, int, int)); +extern int sys_mount __P((int, int, int)); +extern int sys_umount __P((int, int, int)); +extern int sys_setuid __P((int, int, int)); +extern int sys_getuid __P((int, int, int)); +extern int sys_stime __P((int, int, int)); +extern int sys_ptrace __P((int, int, int)); +extern int sys_alarm __P((int, int, int)); +extern int sys_fstat __P((int, int, int)); +extern int sys_pause __P((int, int, int)); +extern int sys_utime __P((int, int, int)); +extern int sys_stty __P((int, int, int)); +extern int sys_gtty __P((int, int, int)); +extern int sys_access __P((int, int, int)); +extern int sys_nice __P((int, int, int)); +extern int sys_ftime __P((int, int, int)); +extern int sys_sync __P((int, int, int)); +extern int sys_kill __P((int, int, int)); +extern int sys_rename __P((int, int, int)); +extern int sys_mkdir __P((int, int, int)); +extern int sys_rmdir __P((int, int, int)); +extern int sys_pipe __P((int, int, int)); +extern int sys_times __P((int, int, int)); +extern int sys_prof __P((int, int, int)); +extern int sys_setgid __P((int, int, int)); +extern int sys_getgid __P((int, int, int)); +extern int sys_signal __P((int, int, int)); +extern int sys_acct __P((int, int, int)); +extern int sys_plock __P((int, int, int)); +extern int sys_ioctl __P((int, int, int)); +extern int sys_fcntl __P((int, int, int)); +extern int sys_exec __P((int, int, int)); +extern int sys_umask __P((int, int, int)); +extern int sys_chroot __P((int, int, int)); +extern int sys_sigaction __P((int, int, int)); +extern int sys_sigsuspend __P((int, int, int)); +extern int sys_sigpending __P((int, int, int)); +extern int sys_sigprocmask __P((int, int, int)); +extern int sys_sigreturn __P((int, int, int)); +extern int sys_reboot __P((int, int, int)); @@ -0,0 +1,11 @@ +main() +{ + static char str[2] = "X"; + + write(1, "Starting\n", 9); + + str[0] = 'A' +(fork()!=0); + + for(;;) + write(1, str, 1); +} @@ -0,0 +1,368 @@ +/* + * This does a determination of the cpu type that is actually being used. + * It can determine the CPU on anything upto and including a 386 accuratly + * whatever mode the CPU is in (This is 16 bit code) + * + * For Post 386 interpretation the argument must be set to 1, if this is done + * an attempt to determine the CPU type will be made using MSDOS calls and + * potentially Illegal instructions. + * + * If STANDALONE is defined this will decode and print the output from cputype + * + * $ cputype # Call cputype(0) and interpret + * $ cputype + # Call cputype(1) get a SIGILL (or perhaps interpret) + * + * NOTE: This code is COPYRIGHT and not under the GNU Lib copyright, this + * may be distributed freely as source or as a standalone binary + * compiled from this unmodified source. + * + * You may use the cputype() function in your own personal code. + * You may distribute a binary version of code containing the + * cputype() function if either you distribute this source with + * the binary version or distribute a clear reference to a freely + * available copy of this source code and the source code to the + * rest of your package with the binary version of the package. + * + * (C) Copyright R de Bath 1989-1996 + */ + +#ifdef STANDALONE +#define cputype cpu + +#include <stdio.h> +#ifndef __MSDOS__ +#include <signal.h> +#endif + +char * name_808x[] = { +"8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone" +}; + +char * name_8018x[] = { +"80188", "80186", "8018x Clone" +}; + +char * name = "80x86?"; + +void +main(argc, argv) +int argc; char **argv; +{ + int c, major, flg, fpu; +#ifdef SIGFPE + signal(SIGFPE, SIG_IGN); +#endif + + prts("Cpu identifier - (C) R de Bath <rdebath@cix.compulink.co.uk>\n"); + + c = cputype(argc!=1); + fpu = (c<0); major = ((c>>8)&0x1F); c &= 0xFF; + + prts("Cpu is an "); + if( major == 0 ) + { + if( c > 6 ) c = 6; + prts(name_808x[c]); + } + else if( major == 1 ) + { + if( c > 3 ) c = 3; + prts(name_8018x[c]); + } + else + { + name[2] = "0123456789ABCDEF"[major&0xF]; + name[5] = (major>15?'+':'\0'); + prts(name); + if(c&0x01) prts(" in protected mode"); + prts(" MSW= "); + if( c&0x10 ) prts("ET,"); else prts("--,"); + if( c&0x08 ) prts("TS,"); else prts("--,"); + if( c&0x04 ) prts("EM,"); else prts("--,"); + if( c&0x02 ) prts("MP,"); else prts("--,"); + if( c&0x01 ) prts("PE\n"); else prts("--\n"); + + if( !fpu && ( c&0x06) ) + prts("An FPU appears to exist but it is unavailable\n"); + else + { + if( c&0x02 ) prts("Math processor requires WAIT\n"); + if( c&0x04 ) prts("Emulated math present\n"); + if( c&0x08 ) prts("Math processor belongs to a different process\n"); + /* if( c&0x10 ) prts("Humm\n"); */ + } + } + if( fpu ) prts("FPU available for use\n"); + + exit(0); +} + +prts(s) +char * s; +{ + write(1, s, strlen(s)); +} +#endif + +/* + * The assembler for CPU determination. + * + * Improvements and additional CPUs are solicited. + */ + +#ifdef __AS386_16__ +#asm + .text +#ifdef STANDALONE +export _cpu +_cpu: +#else +export _cputype +_cputype: +#endif + ; First save everything ... + push bp + mov bp,sp + push ds + push es + push bx + push cx + push dx + pushf +#if __FIRST_ARG_IN_AX__ + mov cx, ax ; Collect the flag +#else + mov cx, [bp+4] ; Collect the flag +#endif + + ; Tiny mode code ... + mov ax, cs + mov es, ax + mov ds, ax + mov bx, #0 ; Init to 8086 + + ; First easy check is it a 286 or better ... + push sp + pop ax + cmp ax, sp + jz ge286 + br pre286 + + ; Come here when we`re done (286+) +cpu_prot: + ; .286P + smsw ax ; Fetch 5 LSB of MSW (PE,MP,EP,...) + and al,#31 + mov bl,al + + ; Check for FPU + fninit + xor ax,ax + push ax + mov bp,sp + fnstcw word ptr [bp] + pop ax + cmp ah,#3 + jne cpuend + or bh,#$80 + + ; Another check for FPU *BUT* I think this only get`s 287+ +; finit +; fstsw ax +; or al,al +; jnz cpuend +; or bh,#$80 + + ; .8086 +cpuend: + mov ax, bx + popf + pop dx + pop cx + pop bx + pop es + pop ds + pop bp + ret + +ge286: ; .286P + ; Does the caller want the exact CPU + cmp cx,#0 + jne try_486 + +; Simple test for a 286 ... + + mov bh,#2 ; Major CPU type >= 80286 + ; What`s the contents of the GDT pointer + sub sp,#6 + mov bp,sp + sgdt [bp] + add sp,#4 + pop ax ; For 286, ah can only be 0xFF + inc ah + jz cpu_prot + mov bh,#$13 ; Major CPU type >= 80386 + +#ifdef __MSDOS__ + smsw ax ; If we`re in MSDOS and running in real mode + ror ax,#1 ; we can do the int 6 detection. + jnc try_486 +#endif + + jmp cpu_prot ; Assume 486 test will NOT work in prot mode + + ; This is an alternate way of finding a 386 ... + ; But it *can* be hidden by V86 mode. +; pushf +; mov ax,#$7000 +; push ax +; popf +; pushf +; pop ax +; popf +; and ax,#$7000 +; jz is_a_286 + +try_486: + ; This trys to trap undefined instructions + ; it may not work if the CPU is in protected mode + ; Note: This code works for anything 286+ + cli + push bp + mov bp, sp + mov ax,#$3506 + int #$21 ; WARNING - DOS DOS DOS DOS DOS !!!!! + mov [vector+2], es + mov [vector], bx + mov ax,#$2506 + lea dx, [int6] + int #$21 + mov bh,#2 ; 286 + + ; .486 +test386: + mov ebx,#$00040300 ; 386 or 486 +test486: + bswap ebx ; Byte twiddle now 486 + + mov ax,#1 +do_cpuid: + db $0F ; CPUID instruction + db $A2 + + mov ax,#1 ; And again cause of Nasty EMM386s + db $0F ; CPUID instruction + db $A2 + + and ah,#15 ; Select family number + mov bh,ah ; put it where we want it + + ; .286P +fail386: + mov ax, #$2506 + mov dx, [vector] + mov ds, [vector+2] + int #$21 + pop bp + sti + br cpu_prot + + + ; Tests for processors before the 80286 ... + ; .8086 +pre286: + ; Is it an 8018x ? These mask shifts to less that 32 bits + mov cl,#32 + mov ax, #$0100 + shl ax,cl + mov bx, ax + jnz test8 + + ; Try for an NEC V20/30 + mov ax, #$0208 + db $D5 + db 16 ; Only the 8088 actually checks the arg to AAD + cmp al, #$28 ; as intel ran out of microcode space + jz cmos + mov bx,#4 ; NEC V20 + jmp test8 + + ; The CMOS 8088/6 had the bug with rep lods repaired. +cmos: push si + sti + mov cx, #$FFFF + rep + lodsb + pop si + or cx,cx + jne test8 + mov bx,#2 ; Intel 80C88 + + ; This tests the prefetch of the CPU, 8 bit ones have 4 bytes + ; 16 bit cpus have a queue of 6 bytes. +test8: push di + push bx + mov dx,#0 + mov bx,#4 + std + mov al,#$90 + +retest: lea di,[_nop] + cli + mov cx,#3 + rep + stosb + nop + nop + nop + nop +_inc: inc dx + nop +_nop: nop + sti + mov byte ptr [_inc], #$42 + dec bx + jnz retest + pop bx + cmp dx,#0 + jz done8 + inc bx +done8: pop di + cld + + br cpuend + + + ; Function called by the illegal instruction trap +int6: + mov sp, bp + jmp fail386 + +; This was the old way, didn't always work tho. +; push bp +; mov bp, sp +; push ax +; mov ax,cs +; cmp 4[bp],ax +; pop ax +; jnz pass +; cmp bh,#2 +; je move23 +; cmp bh,#3 +; je move34 +; add [bp+2], #(fail386 - do_cpuid) +; jmp return +;move34: add [bp+2], #(fail386 - test486) +; jmp return +;move23: add [bp+2], #(fail386 - test386) +;return: pop bp +; iret +; +;pass: pop bp +; jmp [vector] + +vector: dd 0 + +#endasm + +#endif |