summaryrefslogtreecommitdiff
path: root/libc/msdos
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 21:25:23 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:54 +0200
commitdcc973ea3e31710429858c99d4f040334ac67c06 (patch)
tree8883b902eb18eba489957b7f03caa491fd7992a7 /libc/msdos
parentfe22c37817ce338fbbc90b239320248c270957fa (diff)
downloaddev86-dcc973ea3e31710429858c99d4f040334ac67c06.tar.gz
Import Dev86-0.0.5.tar.gzv0.0.5
Diffstat (limited to 'libc/msdos')
-rw-r--r--libc/msdos/Config1
-rw-r--r--libc/msdos/Makefile36
-rw-r--r--libc/msdos/Notes8
-rw-r--r--libc/msdos/i86.c163
-rw-r--r--libc/msdos/msdos.c540
5 files changed, 748 insertions, 0 deletions
diff --git a/libc/msdos/Config b/libc/msdos/Config
new file mode 100644
index 0000000..ec28084
--- /dev/null
+++ b/libc/msdos/Config
@@ -0,0 +1 @@
+msdos: Msdos system calls
diff --git a/libc/msdos/Makefile b/libc/msdos/Makefile
new file mode 100644
index 0000000..2dd3497
--- /dev/null
+++ b/libc/msdos/Makefile
@@ -0,0 +1,36 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+ASRC=msdos.c
+AOBJ= dos_start.o __mkargv.o dos__fconv.o dos_read.o dos_write.o \
+ dos_open.o dos_close.o dos_unlink.o dos_lseek.o \
+ dos_segalloc.o dos_setvect.o dos_getvect.o dos_isatty.o
+
+BSRC=i86.c
+BOBJ= __set_es.o __peek_es.o __poke_es.o __deek_es.o __strchr_es.o
+
+ifeq ($(PLATFORM),i86-DOS)
+OBJ=$(AOBJ) $(BOBJ)
+else
+OBJ=$(BOBJ)
+endif
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f *.o libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+$(BOBJ): $(BSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(BSRC)
+
diff --git a/libc/msdos/Notes b/libc/msdos/Notes
new file mode 100644
index 0000000..b775dff
--- /dev/null
+++ b/libc/msdos/Notes
@@ -0,0 +1,8 @@
+This is currently a very cutdown version of the syslib.
+
+This also currently does nothing about the difference between 'TEXT' and
+'BINARY' modes but I think that this level of operation should be pure
+binary, the 'TEXT' mode is more suited to stdio where an "fopen(f, "rb")"
+is more reasonable and probably won't break on other OSs.
+
+-Robert.
diff --git a/libc/msdos/i86.c b/libc/msdos/i86.c
new file mode 100644
index 0000000..0613756
--- /dev/null
+++ b/libc/msdos/i86.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+/*
+ * These functions will not normally be useful for Linux-8086. But they
+ * can be used and may be useful in the kernel.
+ */
+
+#ifdef __AS386_16__
+
+#ifdef L___set_es
+unsigned int
+__get_ds()
+{
+#asm
+ mov ax,ds
+#endasm
+}
+
+unsigned int
+__get_es()
+{
+#asm
+ mov ax,es
+#endasm
+}
+
+void
+__set_es(seg)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov es,ax
+#else
+ mov bx,sp
+ mov es,[bx+2]
+#endif
+#endasm
+}
+#endif
+
+#ifdef L___peek_es
+int
+__peek_es(off)
+unsigned int off;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov al,[bx]
+ xor ah,ah
+#endasm
+}
+#endif
+
+#ifdef L___poke_es
+int
+__poke_es(off, value)
+unsigned int off;
+int value;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov bx,[bx+2]
+ xchg ax,bx
+#else
+ mov bx,sp
+ mov ax,[bx+4]
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov [bx],al
+ xor ah,ah
+#endasm
+}
+#endif
+
+#ifdef L___deek_es
+int
+__deek_es(off)
+unsigned int off;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov ax,[bx]
+#endasm
+}
+#endif
+
+#ifdef L___strchr_es
+char *
+__strchr_es(s, c)
+char * s;
+int c;
+{
+#asm
+ mov bx,sp
+ push si
+#if __FIRST_ARG_IN_AX__
+ mov bx,[bx+2]
+ mov si,ax
+#else
+ mov si,[bx+2]
+ mov bx,[bx+4]
+#endif
+ xor ax,ax
+
+#ifdef PARANOID
+ cld
+#endif
+ push ds
+ push es
+ pop ds
+
+in_loop:
+ lodsb
+ cmp al,bl
+ jz got_it
+ or al,al
+ jnz in_loop
+ pop ds
+ pop si
+ ret
+got_it:
+ lea ax,[si-1]
+ pop ds
+ pop si
+
+#endasm
+}
+#endif
+
+#ifdef L___strchr_es
+char *
+__strnget_es(d, s, c)
+char *d, *s;
+int c;
+{
+ int ds, es;
+ char *p = __strchr_es(s, '\0');
+ if(p != 0 && p-s < c)
+ c = p-s+1;
+ ds = __get_ds();
+ es = __get_es();
+
+ __movedata(es, s, ds, d, c);
+}
+#endif
+
+#endif /* __AS386_16__ */
diff --git a/libc/msdos/msdos.c b/libc/msdos/msdos.c
new file mode 100644
index 0000000..02c35db
--- /dev/null
+++ b/libc/msdos/msdos.c
@@ -0,0 +1,540 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __MSDOS__
+
+#include <dos.h>
+#include <fcntl.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_dos_start
+
+static char * argdef[2] = { "C" };
+char ** __argv =argdef;
+char ** environ =argdef+1;
+
+int __argc =1;
+void (*__cleanup)() = 0;
+
+#asm
+ .data
+export ___envseg
+___envseg:
+ .word 0
+
+export ___psp
+___psp:
+ .word 0
+
+ .text
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+ inc sp
+ inc sp
+__exit: ! _exit(rv)
+ mov bx,sp
+ mov ax,[bx+2]
+ mov ah,#$4c
+ int #$21
+dos_1_exit:
+ int #$20
+
+ .text
+export ___cstartup ! Crt0 startup
+___cstartup:
+ mov ax,#$3000 ! Get DOS version
+ int $21
+ cmp al,#2 ! DOS 2+ is Ok
+ jb dos_1_exit
+
+ mov dx,cs ! Current CS
+ add dx,#__segoff ! This var generated by the linker
+ mov ds,dx ! Correct DS
+
+ mov [___psp],es ! PSP segment
+ seg es
+ mov ax,[$2c]
+ mov [___envseg],ax ! Enviroment Segment
+
+ ! Now need to free some RAM
+ seg es
+ mov bx,[2] ! Top of Ram
+ mov ax,ds
+ add ax,#4096 ! Top of 64k data seg
+ jc use_tor ! Oops, wrapped
+ cmp ax,bx
+ jnc use_tor ! Bigger than tor
+ mov bx,ax
+use_tor:
+ mov ax,cs ! Work out how big the memseg is needed
+ sub bx,ax
+ mov ah,#$4A ! Set it
+ int $21
+ jnc set_stack ! Good.
+ ! Ooops, problem..
+ ! BX is now how big it can be so set that.
+ ! FIXME should check for BSS v Stack overlap
+ mov ah,#$4A
+ int $21
+
+set_stack: ! Now set SS to the same as DS
+ sub bx,#__segoff ! And SP to the top of available memory.
+ mov cl,#4
+ shl bx,cl
+ sub bx,#2
+ mov ss,dx
+ mov sp,bx
+
+zap_bss: ! Clear the BSS
+ mov es,dx ! ES now data seg
+ mov di,#__edata
+ mov cx,#__end
+ sub cx,di
+ xor ax,ax
+ cld
+ rep
+ stosb
+
+ call ___mkargv ! Fetch the arguments and enviroment
+ push [_environ]
+ push [___argv]
+ push [___argc]
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+ call [si] ! Call the function
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+ push ax ! At the end the last called was main() push it`s
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+ loc 2
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+data_start:
+
+ .text
+
+#endasm
+
+__E_nosys()
+{
+#asm
+ .text
+
+export sys_call5
+export sys_call4
+export sys_call3
+export sys_call2
+export sys_call1
+export sys_call0
+sys_call5: ! Trap the unemulated Linux86 syscalls
+sys_call4:
+sys_call3:
+sys_call2:
+sys_call1:
+sys_call0:
+
+#endasm
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifdef L___mkargv
+
+extern char ** environ;
+extern char ** __argv;
+extern int __argc;
+
+__mkargv()
+{
+ int length, i, argc=1, s=0;
+ char *ptr, *p;
+ __set_es(__psp); /* Pointer to the args */
+ length = __peek_es(0x80); /* Length of cmd line */
+ if( length > 0 )
+ {
+ ptr = (char*) sbrk(length+1); /* Allocate some space */
+
+ for(i=0; i<length; i++) /* Copy it in. */
+ {
+ ptr[i] = __peek_es(0x81+i);
+ if( ptr[i] != ' ' && s == 0 ) { argc++; s=1; }
+ if( ptr[i] == ' ' && s == 1 ) s=0;
+ }
+ ptr[length]=0;
+
+ p= __argv[0];
+ __argv = (char**) sbrk((argc+1)*sizeof(char*));
+ __argv[0] = p; /* FIXME: The real command can be found */
+ __argc=argc;
+
+ argc=1; s=0;
+ for(i=0; i<length; i++)
+ {
+ if( ptr[i] != ' ' && s == 0 ) { __argv[argc++] = ptr+i; s=1; }
+ if( ptr[i] == ' ' && s == 1 ) { ptr[i] = '\0'; s=0; }
+ }
+ __argv[argc] = 0;
+ }
+}
+#endif
+
+#ifdef L_dos__fconv
+/* This function converts filenames from unix like to DOS. */
+char *
+__fconv(fname)
+char * fname;
+{
+static char buf1[66], buf2[66], *str = 0;
+ register char *p, ch;
+ int dot = 0;
+
+ if( strcmp("/dev/tty", fname) == 0 ) return "CON:";
+
+ if( str == buf1 ) str = buf2; else str = buf1;
+
+ p = str;
+ if( strncmp("/mnt/", fname, 5) == 0 )
+ {
+ strcpy(p, "A:"); p+=2; fname+=4;
+ }
+ /*
+ * POSS:
+ * open("/name/*", ...); looks for an environ var PATH_name=c:\x\y\z
+ */
+
+ while((ch = *fname++) && p < str+65)
+ {
+ if( ( ch >= 'a' && ch <= 'z' )
+ || ( ch >= '0' && ch <= '9' )
+ || ch == ':' || ch == '%' || ch == '-' || ch == '$' )
+ ;
+ else if( ch >= 'A' && ch <= 'Z' )
+ ch = ch-'A'+'a';
+ else if( ch == '.' && dot == 0 )
+ dot = 1;
+ else if( ch == '/' || ch == '\\' )
+ {
+ dot = 0; ch = '\\';
+ }
+ else ch = '_';
+
+ *p++ = ch;
+ }
+ *p++ = '\0';
+ return str;
+}
+#endif
+
+#ifdef L_dos_read
+int
+read(fd, ptr, len)
+int fd;
+char *ptr;
+unsigned len;
+{
+#asm
+ mov bx,sp
+ mov cx,[bx+6]
+ mov dx,[bx+4]
+ mov bx,[bx+2]
+ mov ah,#$3f
+ int #$21
+ jnc readok
+ mov ax,#-1
+readok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_write
+int
+write(fd, ptr, len)
+int fd;
+char *ptr;
+unsigned len;
+{
+#asm
+ mov bx,sp
+ mov cx,[bx+6]
+ mov dx,[bx+4]
+ mov bx,[bx+2]
+ mov ah,#$40
+ int #$21
+ jnc writeok
+ mov ax,#-1
+writeok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_open
+int
+open(fname, type, cmode)
+char * fname;
+int type;
+int cmode;
+{
+ register char * nname = __fconv(fname);
+ int creat_mode = 0;
+ int rv;
+
+ if( (cmode & 0222) == 0 ) creat_mode = 1;
+
+ /* BzzzT. Assume these flags both mean the merge of them */
+ /* BzzzT. Also ignore O_EXCL */
+ if( type & (O_TRUNC|O_CREAT) )
+ rv = __dos_creat(nname, creat_mode);
+
+ else
+ /* Warn, this assumes the standard vals for O_RDWR, O_RDONLY, O_WRONLY */
+ rv = __dos_open(nname, type&O_ACCMODE);
+ if( rv < 0 ) errno=ENOENT;
+ return rv;
+}
+
+__dos_open(fname, mode)
+{
+#asm
+ mov bx,sp
+ mov dx,[bx+2] ;ds:dx points to source string
+ mov al,[bx+4] ;access code
+ mov ah,#$3d ;ask for a open
+ int #$21
+ jnc openok ;return handle if no error
+ mov ax,#-1 ;return -1 if error
+openok:
+#endasm
+}
+
+__dos_creat(fname)
+char * fname;
+{
+#asm
+ mov bx,sp
+ mov dx,[bx+2] ;ds:dx points to source string
+ xor cx,cx ;normal attributes
+ mov ah,#$3c ;ask for a create
+ int #$21
+ jnc creok ;return handle if no error
+ mov ax,#-1 ;return -1 if error
+creok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_close
+close(fd)
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2] ;file handle
+ mov ah,#$3e ;ask for a close
+ int #$21
+ mov ax,0 ;return 0 if no error
+ jnc closeok
+ mov ax,#-1 ;return -1 if error
+closeok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_unlink
+unlink(fname)
+char * fname;
+{
+#asm
+ mov bx,sp
+ push [bx+2]
+ call ___fconv
+ inc sp
+ inc sp
+ mov dx,ax ;ds:dx points to source string
+ mov ah,#$41 ;ask for a unlink
+ int #$21
+ mov ax,0 ;assume no errors
+ jnc unlok
+ mov ax,#-1 ;return -1 if error
+unlok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_lseek
+long
+lseek(fd, offset, mode)
+int fd, mode;
+long offset;
+{
+#asm
+ mov bx,sp
+ mov al,[bx+8] ;mode of seek (0 to 2)
+ mov dx,[bx+4] ;cx:dx is long offset
+ mov cx,[bx+6]
+ mov bx,[bx+2] ;file handle
+ mov ah,#$42
+ int #$21 ;do the lseek
+ jnc seekok
+ mov ax,#-1 ;return -1 if error
+ mov dx,ax
+seekok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_segalloc
+unsigned int
+__segalloc(paracount)
+unsigned int paracount;
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2]
+ mov ah,#$48
+ int $21
+ jnc ok
+ mov ax,#0
+ok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_setvect
+void
+__setvect(i,j)
+int i;
+long j;
+{
+#asm
+ mov bx,sp
+ mov ax,[bx+2]
+ mov dx,[bx+4]
+ mov bx,[bx+6]
+ push ds
+ test bx,bx
+ jnz got_seg
+ mov bx,cs
+got_seg:
+ mov ds,bx
+ mov ah,#$25
+ int $21
+ pop ds
+#endasm
+}
+#endif
+
+#ifdef L_dos_getvect
+long
+__getvect(vecno)
+int vecno;
+{
+#asm
+ mov bx,sp
+ mov ax,[bx+2]
+ mov ah,#$35
+ push es
+ int #$21
+ mov dx,es
+ mov ax,bx
+ pop es
+#endasm
+}
+#endif
+
+#ifdef L_dos_isatty
+isatty(fd)
+int fd;
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2]
+ mov ah,#$44
+ mov al,#0
+ int #$21
+ xor ax,ax
+ test dx,#$80
+ jz not_tty
+ inc ax
+not_tty:
+#endasm
+}
+#endif
+
+#endif /* __MSDOS__ */
+#endif /* __AS386_16__ */
+#endif /* !__FIRST_ARG_IN_AX__ */
+
+/*
+# Name No Args Flag, comment
+CHDIR 12 1
+TIME 13 1 * No long return val, arg _must_ exist.
+MKNOD 14 3
+CHMOD 15 2
+CHOWN 16 3
+BRK 17 1 * This is only to tell the system
+STAT 18 2
+GETPID 20 1 * This gets both pid & ppid
+MOUNT 21 3 * Need more args & no ELKS
+UMOUNT 22 1 . No ELKS
+SETUID 23 1
+GETUID 24 1 * This gets both uid and euid
+STIME 25 2 . No ELKS should be 1 LONG arg
+PTRACE 26 X +
+ALARM 27 2 ? No unused return.
+FSTAT 28 2
+PAUSE 29 0
+UTIME 30 2
+STTY 31 2 . ELKS ain't got this and it'll probably change
+GTTY 32 2 . ELKS ain't got this and it'll probably change
+ACCESS 33 2
+NICE 34 1
+FTIME 35 1 . ELKS ain't got this.
+SYNC 36 0
+KILL 37 2
+RENAME 38 2
+MKDIR 39 2
+RMDIR 40 1
+DUP 41 X - Using nasty fcntl function
+PIPE 42 1
+TIMES 43 1
+PROF 44 X +
+SETGID 46 1
+GETGID 47 1 * This gets both gid and egid
+SIGNAL 48 2 +
+ACCT 51 X +
+PLOCK 53 X +
+IOCTL 54 3
+FCNTL 55 3
+EXEC 59 2 ?
+UMASK 60 1
+CHROOT 61 1
+SIGACTION 71 X
+SIGSUSPEND 72 X
+SIGPENDING 73 X
+SIGPROCMASK 74 X
+SIGRETURN 75 X
+REBOOT 76 3 . No ELKS and the magic number will be diff.
+*/
+