summaryrefslogtreecommitdiff
path: root/libc/bios
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bios')
-rw-r--r--libc/bios/Config1
-rw-r--r--libc/bios/Makefile35
-rw-r--r--libc/bios/README10
-rw-r--r--libc/bios/bios.c230
-rw-r--r--libc/bios/bios_vid.c489
5 files changed, 765 insertions, 0 deletions
diff --git a/libc/bios/Config b/libc/bios/Config
new file mode 100644
index 0000000..e7f1971
--- /dev/null
+++ b/libc/bios/Config
@@ -0,0 +1 @@
+bios: Minimal syscalls for BIOS level
diff --git a/libc/bios/Makefile b/libc/bios/Makefile
new file mode 100644
index 0000000..5fcc964
--- /dev/null
+++ b/libc/bios/Makefile
@@ -0,0 +1,35 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+ifeq ($(LIB_OS),BIOS)
+ASRC=bios.c
+AOBJ=bios_start.o bios_isatty.o \
+ bios_open.o bios_read.o bios_write.o bios_lseek.o bios_close.o
+
+BSRC=bios_vid.c
+BOBJ=bios_putc.o bios_getc.o bios_khit.o bios_rdline.o
+
+OBJ=$(AOBJ) $(BOBJ)
+
+CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS)
+
+all: $(LIBC)($(OBJ))
+ @:
+
+$(LIBC)($(AOBJ)): $(ASRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+
+$(LIBC)($(BOBJ)): $(BSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+ $(RM) $*.o
+else
+all:
+ @:
+endif
+
+clean:
+ rm -f *.o libc.a
diff --git a/libc/bios/README b/libc/bios/README
new file mode 100644
index 0000000..cc883e1
--- /dev/null
+++ b/libc/bios/README
@@ -0,0 +1,10 @@
+Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+This is a very simple set of functions for standalone executables.
+
+There is a choice as to which console type you want to use, I think
+the VT52 clone is best.
+
+-Robert
diff --git a/libc/bios/bios.c b/libc/bios/bios.c
new file mode 100644
index 0000000..a8d2079
--- /dev/null
+++ b/libc/bios/bios.c
@@ -0,0 +1,230 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.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 __STANDALONE__
+
+#include <dos.h>
+#include <fcntl.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_bios_start
+char ** environ = { 0 };
+
+void (*__cleanup)() = 0;
+
+#asm
+ .data
+export ___argr
+___argr:
+ .word 0,0,0,0,0,0,0 ! A struct REGS
+defarg:
+ .word boot_str, 0
+boot_str:
+ .asciz "boot"
+loop_save:
+ .word 0
+
+ .text
+export ___cstartup ! Crt0 startup
+___cstartup:
+ mov ___argr+0,ax
+ mov ___argr+2,bx
+ mov ___argr+4,cx
+ mov ___argr+6,dx
+ mov ___argr+8,si
+ mov ___argr+10,di
+
+zap_bss: ! Clear the BSS
+ mov ax,ds
+ mov es,ax ! ES now data seg
+ mov di,#__edata
+ mov cx,#__end
+ sub cx,di
+ xor ax,ax
+ cld
+ rep
+ stosb
+
+ push [_environ]
+ mov ax,#defarg ! Don`t define __mkargv, standalone programs don`t
+ push ax ! get any arguments.
+ mov ax,#1
+ push ax
+
+ mov bx,#auto_start ! Pointer to first autostart function
+auto_run:
+ mov [loop_save],bx
+ mov bx,[bx]
+ test bx,bx
+ jz no_entry
+ call bx ! Call the function
+no_entry:
+ mov bx,[loop_save]
+ inc bx ! next
+ inc bx
+ 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
+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
+
+export __exit
+__exit:
+ xor ax,ax
+ mov es,ax
+ mov ax,cs
+ seg es
+ mov [$E6*4+2],ax
+ mov ax,#reti_ins
+ seg es
+ mov [$E6*4],ax
+ mov ax,#$FFFF
+ int $E6 ! Try to exit DOSEMU
+ ! If we get here we`re not in dosemu.
+ seg es
+ mov [$472],#$1234 ! Warm reboot.
+ jmpi $0000,$FFFF
+reti_ins:
+ reti
+
+#endasm
+
+#endif
+
+/****************************************************************************/
+
+#ifdef L___file_3
+
+/* If the block function does track buffering this should be ok ... */
+struct {
+ int (*block_rw)(); /* Args (rwoc, &buffer, blockno) 1k blocks */
+ /* 0 = read, 1 = write */
+ /* 2 = open, buffer is fname ptr */
+ /* 3 = close, other args ignored */
+ long offset;
+
+ int flags;
+ long block_num;
+ char buffer[1024];
+} __file_3_data;
+
+#define FILE3_OPEN 1 /* File is open */
+#define FILE3_DATA 2 /* buffer has valid contents */
+#define FILE3_DIRTY 4 /* buffer has been modified */
+
+#endif
+
+#ifdef L_bios_write
+write(fd,buf,len)
+int fd,len;
+char * buf;
+{
+ register int v, c;
+ if(fd == 1 || fd == 2)
+ {
+ for(v=len; v>0; v--)
+ {
+ c= *buf++;
+ if( c == '\n') bios_putc('\r');
+ bios_putc(c);
+ }
+ return len;
+ }
+ errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_read
+read(fd,buf,len)
+int fd,len;
+char * buf;
+{
+ if(fd == 0) return bios_rdline(buf, len);
+ errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_lseek
+long
+lseek(fd, offt, whence)
+int fd, whence;
+long offt;
+{
+ if( fd >= 0 && fd <= 2 ) errno = ESPIPE;
+ else errno = EBADF;
+ return -1L;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_open
+open(name, flags, mode)
+char * name;
+int flags, mode;
+{
+ errno = ENOENT;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_close
+close(fd)
+int fd;
+{
+ if( fd >= 0 && fd <= 2 ) errno = ENOSYS;
+ else errno = EBADF;
+ return -1;
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_isatty
+isatty(fd)
+int fd;
+{
+ if( fd >= 0 && fd <= 2 ) return 1;
+ return 0;
+}
+#endif
+
+/****************************************************************************/
+
+#endif
+#endif
+#endif
diff --git a/libc/bios/bios_vid.c b/libc/bios/bios_vid.c
new file mode 100644
index 0000000..db2e91d
--- /dev/null
+++ b/libc/bios/bios_vid.c
@@ -0,0 +1,489 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* Various possible console types */
+#define VT52_CON /* IMO the best, no clear to EOS/EOL yet */
+#define XANSI_CON /* Largest but still not complete */
+#define XDUMB_CON /* Can't do much */
+#define XSPEC_CON /* Incomplete, best for slow links */
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __STANDALONE__
+
+#include <dos.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_bios_putc
+#define CTRL(x) ((x)&0x1F)
+static int last_attr = 0x07;
+static int con_mode;
+static unsigned char con_height = 24, con_width = 79;
+
+static int con_colour = 0;
+static unsigned char con_row, con_col;
+
+#ifdef VT52_CON
+bios_putc(c)
+int c;
+{
+static int ctrl = 0;
+ int new_attr;
+ if( con_mode==0 ) asm_coninit();
+
+ switch( ctrl )
+ {
+ case 1:
+ ctrl=0;
+ switch(c)
+ {
+ case 'A': if( con_row ) con_row--; asm_cpos(con_row, con_col); break;
+ case 'B': if( con_row != con_height ) con_row++;
+ asm_cpos(con_row, con_col); break;
+ case 'C': if( con_col != con_height ) con_col++;
+ asm_cpos(con_row, con_col); break;
+ case 'D': if( con_col ) con_col--; asm_cpos(con_row, con_col); break;
+ case 'E': last_attr = 0x07; asm_cls();
+ case 'H': asm_cpos(0,0); break;
+ case 'J': asm_cls(); break;
+ case 'K': break;
+ case 'R': ctrl = 2; break; /* Foreground */
+ case 'S': ctrl = 3; break; /* Background */
+ case 'Y': ctrl = 4; break; /* ttypos */
+ }
+ break;
+ case 2: ctrl=0; new_attr = (last_attr & 0xF0) + (c&0xF);
+ if(0) {
+ case 3: ctrl=0; new_attr = (last_attr & 0x0F) + (c<<4);
+ }
+ switch(c)
+ {
+ case '_': if( !con_colour ) last_attr = (last_attr&0x88) + 1;
+ break;
+ case '!': last_attr = (last_attr&0x88) + 0x70; break;
+ case ' ': last_attr = 0x07; break;
+ case '+': last_attr |= 0x08; break;
+ case '*': last_attr |= 0x80; break;
+
+ default: if( con_colour )
+ last_attr = new_attr;
+ }
+ break;
+ case 4: ctrl=5; con_col = c-' '; break;
+ case 5: ctrl=0; con_row = c-' '; asm_cpos(con_row, con_col); break;
+ break;
+
+ default:
+ if( c & 0xE0 )
+ { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('I'):
+ asm_putc(' '); /* Only some BIOS's have this, so play safe */
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('['):
+ ctrl = 1;
+ asm_gpos();
+ break;
+ }
+ break;
+ }
+}
+#endif
+
+#ifdef ANSI_CON
+#define MAX_ARGS 8
+static int colconv[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+static int vidcnt = 0;
+static int ansi_2 = 0;
+static int ansi_argc = 0;
+static int ansi_argv[MAX_ARGS];
+
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+
+ if( vidcnt == 0 || c < ' ' || c > '~' )
+ {
+ switch(c & 0xFF)
+ {
+ default:
+ asm_colour(last_attr);
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('['):
+ vidcnt=1;
+ break;
+ }
+ return;
+ }
+
+ /* ... ansi/vt100 interpretation, this collects _all_ ansi control strings */
+ switch(vidcnt)
+ {
+ case 1: for(ansi_argc=0; ansi_argc<MAX_ARGS; ansi_argc++)
+ ansi_argv[ansi_argc] = 0;
+ ansi_2 = 0;
+ ansi_argc = 0;
+ vidcnt++;
+
+ if( c != '[' )
+ {
+ do_ansi(c + 0x1B00, ansi_argc, ansi_argv);
+ vidcnt = 0;
+ }
+ break;
+
+ case 2: if( c == ';' )
+ {
+ if( ansi_argc < MAX_ARGS )
+ ansi_argc++;
+ }
+ else if( c >= '0' && c <= '9' )
+ ansi_argv[ansi_argc] = ansi_argv[ansi_argc] * 10 + c - '0';
+ else if( c >= '@' )
+ {
+ do_ansi(c+ansi_2, ++ansi_argc, ansi_argv);
+ vidcnt = 0;
+ }
+ else
+ ansi_2 = (c<<8);
+ break;
+
+ default: vidcnt = 0; /* This definitly won't happen ... definitly ... */
+ }
+}
+
+do_ansi(ctrl, argc, argv)
+int ctrl, argc, *argv;
+{
+ switch(ctrl)
+ {
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ asm_gpos();
+ if( argv[0] < 1 ) argv[0] = 1;
+ switch(ctrl)
+ {
+ case 'A': if( argv[0]>con_row ) con_row=0; else con_row-=argv[0]; break;
+ case 'B': if( argv[0]+con_row>con_height )
+ con_row = con_height;
+ else
+ con_row += argv[0];
+ break;
+ case 'C': if( argv[0]+con_col>con_width )
+ con_col = con_width;
+ else
+ con_col += argv[0];
+ break;
+ case 'D': if( argv[0]>con_col ) con_col=0; else con_col-=argv[0]; break;
+ }
+ asm_cpos(con_row, con_col);
+ break;
+
+ case 'H':
+ if( --argv[0] < 0 ) argv[0] = 0;
+ if( --argv[1] < 0 ) argv[1] = 0;
+ asm_cpos(argv[0],argv[1]);
+ break;
+ case 'J': if( argv[0] == 2 ) asm_cls();
+ break;
+ case 'm':
+ {
+ int ar;
+ for(ar=0; ar<argc; ar++) switch(argv[ar])
+ {
+ case 0: last_attr = 0x07; break;
+ case 1: last_attr |= 0x08; break;
+ case 5: last_attr |= 0x80; break;
+ case 7: last_attr = 0x70; break;
+ case 30: case 31: case 32: case 33:
+ case 34: case 35: case 36: case 37:
+ if( con_colour )
+ last_attr = ((last_attr&0xF8)|(colconv[argv[ar]-30]));
+ break;
+ case 40: case 41: case 42: case 43:
+ case 44: case 45: case 46: case 47:
+ if( con_colour )
+ last_attr = ((last_attr&0x8F)|((colconv[argv[ar]-40])<<4));
+ break;
+ default: break;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef SPEC_CON
+static char vidbuf[3];
+static int vidcnt=0;
+
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+ if( vidcnt == 0 )
+ {
+ if( c & 0xE0 )
+ { asm_colour(last_attr) ; asm_putc(c); }
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cpos(0,0);
+ asm_cls();
+ break;
+ case CTRL('P'):
+ case CTRL(']'):
+ vidbuf[vidcnt++] = c;
+ break;
+ }
+ }
+ else
+ {
+ vidbuf[vidcnt++] = c;
+ if( vidcnt < 3 &&
+ (vidbuf[0] != CTRL(']') || vidbuf[1] < '`' || vidbuf[1] > 'p'))
+ return;
+
+ if( vidbuf[0] == CTRL('P') )
+ {
+ if( vidbuf[1] >= 32 && vidbuf[1] <= 56
+ && vidbuf[2] >= 32 && vidbuf[2] <= 111 )
+ asm_cpos((vidbuf[1]-32), (vidbuf[2]-32));
+ }
+ else
+ {
+ if( vidbuf[1] >= '`' )
+ last_attr = ( (vidbuf[1]&0xF) | (last_attr&0xF0));
+ else
+ last_attr = ( (vidbuf[2]&0xF) | ((vidbuf[1]&0xF)<<4));
+
+ if( !con_colour )
+ last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70);
+ }
+ vidcnt=0;
+ }
+}
+#endif
+
+#ifdef DUMB_CON
+bios_putc(c)
+int c;
+{
+ if( con_mode==0 ) asm_coninit();
+ if( c & 0xE0 ) asm_putc(c);
+ else switch(c)
+ {
+ default:
+ asm_putc(c);
+ break;
+ case CTRL('L'):
+ asm_cls();
+ case CTRL('^'):
+ asm_cpos(0,0);
+ break;
+ }
+}
+#endif
+
+static asm_coninit()
+{
+#asm
+ mov ax,#$0F00
+ int $10
+ mov _con_mode,ax
+#endasm
+ if( (con_mode &0xFF) > 39 ) con_width = (con_mode>>8);
+ if( (con_mode&0xFF) != 0x7)
+ con_colour = 1;
+}
+
+static asm_putc(c)
+{
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov ax,[bx+2]
+#endif
+ mov ah,#$0E
+ mov bx,#7
+ int $10
+#endasm
+}
+
+static asm_cls()
+{
+#asm
+ push bp ! Bug in some old BIOS`s
+ !mov ax,#$0500
+ !int $10
+ mov ax,#$0600
+ mov bh,_last_attr
+ mov cx,#$0000
+ mov dl,_con_width
+ mov dh,_con_height
+ int $10
+ pop bp
+#endasm
+}
+
+static asm_cpos(r,c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov dh,al
+ mov ax,[bx+2]
+ mov dl,al
+#else
+ mov bx,sp
+ mov ax,[bx+2]
+ mov dh,al
+ mov ax,[bx+4]
+ mov dl,al
+#endif
+ mov ah,#$02
+ mov bx,#7
+ int $10
+#endasm
+}
+
+#ifndef DUMB_CON
+static asm_colour(c)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ mov ah,#$08
+ int $10
+ mov ah,#$09
+ mov cx,#1
+ int $10
+#endasm
+}
+
+static asm_gpos()
+{
+#asm
+ mov ah,#$03
+ mov bx,#7
+ int $10
+ mov [_con_row],dh
+ mov [_con_col],dl
+ mov ax,cx
+#endasm
+}
+#endif
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_rdline
+bios_rdline(buf, len)
+char * buf;
+int len;
+{
+ int ch;
+ int pos=0;
+
+ if( len == 1 )
+ {
+ buf[0]=((ch=bios_getc())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80));
+ return 1;
+ }
+
+ for(ch=0;;)
+ {
+ if(ch != '\003')
+ {
+ ch = bios_getc();
+ if( pos == 0 && (ch&0xFF) == 0 )
+ {
+ buf[0] = ((ch>>8)|0x80);
+ return 1;
+ }
+ ch &= 0x7F;
+ if( ch == '\033' ) ch=3; /* ESC= Interrupt too */
+ }
+ if( ch == '\r' )
+ {
+ bios_putc('\r'); bios_putc('\n');
+ buf[pos++] = '\n';
+ return pos;
+ }
+ if( ch >= ' ' && ch != 0x7F && pos < len-1)
+ bios_putc(buf[pos++] = ch);
+ else if( (ch == '\003' || ch == '\b') && pos > 0 )
+ {
+ bios_putc('\b'); bios_putc(' '); bios_putc('\b');
+ pos--;
+ }
+ else if( ch == '\003' )
+ return 0;
+ else
+ bios_putc('\007');
+ }
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_getc
+bios_getc()
+{
+#asm
+ xor ax,ax
+ int $16
+#endasm
+}
+#endif
+
+/****************************************************************************/
+
+#ifdef L_bios_khit
+bios_khit()
+{
+#asm
+ mov ah,#1
+ int $16
+ jz nokey
+ cmp ax,#0
+ jnz dort
+ mov ax,#3
+dort:
+ ret
+nokey:
+ xor ax,ax
+#endasm
+}
+#endif
+
+/****************************************************************************/
+
+#endif
+#endif
+#endif