From 8aada67545460566c9be6a3e021260509e8edaee Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 17 Nov 2004 05:52:45 +0000 Subject: [PATCH] Very basic operations now work; need to handle line-oriented versus character-oriented input --- com32/include/console.h | 46 ++++++++++++++++++++++++ com32/include/fcntl.h | 24 +++++++++++++ com32/include/stdio.h | 2 ++ com32/include/sys/stat.h | 43 ++++++++++++++++++++++ com32/include/unistd.h | 31 ++++++++++++++++ com32/lib/Makefile | 9 +++-- com32/lib/abort.c | 9 +---- com32/lib/sys/close.c | 15 ++++---- com32/lib/sys/file.h | 50 ++++++++++++++++---------- com32/lib/sys/fileclose.c | 53 +++++++++++++++++++++++++++ com32/lib/sys/fileread.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ com32/lib/sys/isatty.c | 53 +++++++++++++++++++++++++++ com32/lib/sys/open.c | 51 ++++++++++++++++---------- com32/lib/sys/openconsole.c | 52 +++++++++++++++++++++++++++ com32/lib/sys/opendev.c | 62 ++++++++++++++++++++++++++++++++ com32/lib/sys/read.c | 49 ++++--------------------- com32/lib/sys/stdcon.c | 53 +++++++++++++++++++++++++++ com32/lib/sys/stdcon_read.c | 68 +++++++++++++++++++++++++++++++++++ com32/lib/sys/stdcon_write.c | 63 ++++++++++++++++++++++++++++++++ com32/lib/sys/write.c | 21 ++++++----- com32/modules/Makefile | 5 +-- com32/modules/hello.c | 14 ++++++++ 22 files changed, 746 insertions(+), 113 deletions(-) create mode 100644 com32/include/console.h create mode 100644 com32/include/fcntl.h create mode 100644 com32/include/sys/stat.h create mode 100644 com32/include/unistd.h create mode 100644 com32/lib/sys/fileclose.c create mode 100644 com32/lib/sys/fileread.c create mode 100644 com32/lib/sys/isatty.c create mode 100644 com32/lib/sys/openconsole.c create mode 100644 com32/lib/sys/opendev.c create mode 100644 com32/lib/sys/stdcon.c create mode 100644 com32/lib/sys/stdcon_read.c create mode 100644 com32/lib/sys/stdcon_write.c diff --git a/com32/include/console.h b/com32/include/console.h new file mode 100644 index 0000000..78025fb --- /dev/null +++ b/com32/include/console.h @@ -0,0 +1,46 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * console.h + * + * Alternative consoles + */ + +#ifndef _CONSOLE_H +#define _CONSOLE_H + +#include + +struct dev_info; +__extern int openconsole(const struct dev_info *); + +extern const struct dev_info dev_stdcon; + +#endif /* _CONSOLE_H */ + diff --git a/com32/include/fcntl.h b/com32/include/fcntl.h new file mode 100644 index 0000000..b691b5c --- /dev/null +++ b/com32/include/fcntl.h @@ -0,0 +1,24 @@ +/* + * fcntl.h + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +#include +#include +#include + +/* None of these are actually supported, although O_RDONLY works */ +/* Note this is different from the classical Unix way of doing it */ +#define O_RDONLY 1 +#define O_WRONLY 2 +#define O_RDWR 3 +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_TRUNC 01000 +#define O_APPEND 02000 + +__extern int open(const char *, int, ...); + +#endif /* _FCNTL_H */ diff --git a/com32/include/stdio.h b/com32/include/stdio.h index e40a3af..0ebe922 100644 --- a/com32/include/stdio.h +++ b/com32/include/stdio.h @@ -47,6 +47,8 @@ static __inline__ int fileno(FILE *__f) #define stderr __create_file(2) __extern FILE *fopen(const char *, const char *); +struct dev_info; +__extern FILE *fopendev(const struct dev_info *, const char *); static __inline__ FILE *fdopen(int __fd, const char *__m) { diff --git a/com32/include/sys/stat.h b/com32/include/sys/stat.h new file mode 100644 index 0000000..c0afb91 --- /dev/null +++ b/com32/include/sys/stat.h @@ -0,0 +1,43 @@ +/* + * sys/stat.h + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include + +/* We don't use this, but it's there for compatibility */ + +#define S_IFMT 00170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + +#endif /* _SYS_STAT_H */ diff --git a/com32/include/unistd.h b/com32/include/unistd.h new file mode 100644 index 0000000..76ce33a --- /dev/null +++ b/com32/include/unistd.h @@ -0,0 +1,31 @@ +/* + * unistd.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include +#include +#include +#include + +__extern __noreturn _exit(int); + +__extern int open(const char *, int, ...); +struct dev_info; +__extern int opendev(const struct dev_info *, int); +__extern int close(int); + +__extern ssize_t read(int, void *, size_t); +__extern ssize_t write(int, const void *, size_t); + +__extern int isatty(int); + + +/* Standard file descriptor numbers. */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#endif /* _UNISTD_H */ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 6b5ab01..857f8fb 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -77,11 +77,10 @@ LIBOBJS = \ vsprintf.o \ vsscanf.o \ sys/entry.o sys/exit.o \ - sys/open.o \ - sys/fileinfo.o \ - sys/close.o \ - sys/read.o \ - sys/write.o + sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/close.o \ + sys/open.o sys/fileread.o sys/fileclose.o \ + sys/isatty.o sys/openconsole.o \ + sys/stdcon.o sys/stdcon_write.o sys/stdcon_read.o all: libcom32.a diff --git a/com32/lib/abort.c b/com32/lib/abort.c index 9280d98..aacfbbf 100644 --- a/com32/lib/abort.c +++ b/com32/lib/abort.c @@ -4,16 +4,9 @@ #include #include -#include void abort(void) { - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGABRT); - sigprocmask(SIG_UNBLOCK, &set, NULL); - raise(SIGABRT); - _exit(255); /* raise() should have killed us */ + _exit(255); } diff --git a/com32/lib/sys/close.c b/com32/lib/sys/close.c index b81d77e..7af7ff1 100644 --- a/com32/lib/sys/close.c +++ b/com32/lib/sys/close.c @@ -37,21 +37,20 @@ int close(int fd) { - com32sys_t regs; struct file_info *fp = &__file_info[fd]; + int rv = 0; - if ( fd >= NFILES || fp->blocklg2 == 0 ) { + if ( fd >= NFILES || !fp->ops ) { errno = EBADF; return -1; } - if ( fp->filedes ) { - memset(®s, 0, sizeof regs); - regs.eax.w[0] = 0x0008; /* Close file */ - regs.esi.w[0] = fp->filedes; - - __com32.cs_intcall(0x22, ®s, NULL); + if ( fp->ops->close ) { + rv = fp->ops->close(fp); + if ( rv ) + return rv; } + fp->ops = NULL; /* File structure unused */ return 0; } diff --git a/com32/lib/sys/file.h b/com32/lib/sys/file.h index 6a56f58..194c35d 100644 --- a/com32/lib/sys/file.h +++ b/com32/lib/sys/file.h @@ -39,31 +39,45 @@ #include #include -/* Ordinary file */ +/* Device structure; contains the relevant operations */ + +struct file_info; + +#define __DEV_MAGIC 0xf4e7 +#define __DEV_TTY 0x0001 /* TTY - must be bit 0 */ +#define __DEV_FILE 0x0002 /* Ordinary file */ +struct dev_info { + uint16_t dev_magic; /* Magic number */ + uint16_t flags; /* Flags */ + int fileflags; /* Permitted file flags */ + ssize_t (*read)(struct file_info *, void *, size_t); + ssize_t (*write)(struct file_info *, const void *, size_t); + int (*close)(struct file_info *); +}; + +/* File structure */ #define NFILES 32 /* Number of files to support */ #define MAXBLOCK 16384 /* Defined by ABI */ struct file_info { - int blocklg2; /* Blocksize log 2 */ - size_t offset; /* Current file offset */ - size_t length; /* Total file length */ - uint16_t filedes; /* File descriptor */ - uint16_t _filler; /* Unused */ - size_t nbytes; /* Number of bytes available in buffer */ - char *datap; /* Current data pointer */ - char buf[MAXBLOCK]; + const struct dev_info *ops; /* Operations structure */ + + union { + /* Structure used for ordinary files */ + struct { + int blocklg2; /* Blocksize log 2 */ + size_t offset; /* Current file offset */ + size_t length; /* Total file length */ + uint16_t filedes; /* File descriptor */ + uint16_t _filler; /* Unused */ + size_t nbytes; /* Number of bytes available in buffer */ + char *datap; /* Current data pointer */ + char buf[MAXBLOCK]; + } f; + } p; }; extern struct file_info __file_info[NFILES]; -/* Special device (tty et al) */ - -#define __DEV_MAGIC 0x504af4e7 -struct dev_info { - uint32_t dev_magic; /* Magic number */ - ssize_t (*read)(int, void *, size_t); - ssize_t (*write)(int, const void *, size_t); -}; - #endif /* _COM32_SYS_FILE_H */ diff --git a/com32/lib/sys/fileclose.c b/com32/lib/sys/fileclose.c new file mode 100644 index 0000000..5fb89f3 --- /dev/null +++ b/com32/lib/sys/fileclose.c @@ -0,0 +1,53 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * fileclose.c + * + * Close an ordinary file + */ + +#include +#include +#include +#include "file.h" + +int __file_close(struct file_info *fp) +{ + com32sys_t regs; + + if ( fp->p.f.filedes ) { + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0008; /* Close file */ + regs.esi.w[0] = fp->p.f.filedes; + + __com32.cs_intcall(0x22, ®s, NULL); + } + + return 0; +} diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c new file mode 100644 index 0000000..44609f2 --- /dev/null +++ b/com32/lib/sys/fileread.c @@ -0,0 +1,86 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * read.c + * + * Reading from a file + */ + +#include +#include +#include +#include +#include "file.h" + +ssize_t __file_read(struct file_info *fp, void *buf, size_t count) +{ + com32sys_t ireg, oreg; + char *bufp = buf; + size_t n = 0; + size_t ncopy; + + memset(&ireg, 0, sizeof ireg); + ireg.eax.w[0] = 0x0007; /* Read file */ + ireg.esi.w[0] = OFFS(__com32.cs_bounce); + ireg.es = SEG(__com32.cs_bounce); + + while ( count ) { + if ( fp->p.f.nbytes == 0 ) { + if ( fp->p.f.offset >= fp->p.f.length || !fp->p.f.filedes ) + return n; /* As good as it gets... */ + + ireg.esi.w[0] = fp->p.f.filedes; + ireg.ecx.w[0] = MAXBLOCK >> fp->p.f.blocklg2; + + __intcall(0x22, &ireg, &oreg); + + if ( oreg.eflags.l & EFLAGS_CF ) { + errno = EIO; + return -1; + } + + fp->p.f.filedes = ireg.esi.w[0]; + fp->p.f.nbytes = min(fp->p.f.length-fp->p.f.offset, (unsigned)MAXBLOCK); + fp->p.f.datap = fp->p.f.buf; + memcpy(fp->p.f.buf, __com32.cs_bounce, fp->p.f.nbytes); + } + + ncopy = min(count, fp->p.f.nbytes); + memcpy(bufp, fp->p.f.datap, ncopy); + + n += ncopy; + bufp += ncopy; + count -= ncopy; + fp->p.f.datap += ncopy; + fp->p.f.offset += ncopy; + fp->p.f.nbytes -= ncopy; + } + + return n; +} diff --git a/com32/lib/sys/isatty.c b/com32/lib/sys/isatty.c new file mode 100644 index 0000000..8a8e646 --- /dev/null +++ b/com32/lib/sys/isatty.c @@ -0,0 +1,53 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * isatty.c + * + * Return if this is a tty or not + */ + +#include +#include +#include +#include +#include +#include +#include "file.h" + +int isatty(int fd) +{ + struct file_info *fp = &__file_info[fd]; + + if ( fd >= NFILES || !fp->ops ) { + errno = EBADF; + return -1; + } + + return (fp->ops->flags & __DEV_TTY); +} diff --git a/com32/lib/sys/open.c b/com32/lib/sys/open.c index 3f84e5f..27c22ce 100644 --- a/com32/lib/sys/open.c +++ b/com32/lib/sys/open.c @@ -1,7 +1,7 @@ #ident "$Id$" /* ----------------------------------------------------------------------- * * - * Copyright 2003 H. Peter Anvin - All Rights Reserved + * Copyright 2003-2004 H. Peter Anvin - All Rights Reserved * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -29,27 +29,40 @@ #include #include #include +#include +#include #include "file.h" -int open(const char *pathname, int flags, mode_t mode) +/* + * open.c + * + * Open an ordinary file + */ + +extern ssize_t __file_read(struct file_info *, void *, size_t); +extern int __file_close(struct file_info *); + +static const struct dev_info file_dev = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_FILE, + .fileflags = O_RDONLY, + .read = __file_read, + .write = NULL, /* File writes are not supported */ + .close = __file_close, +}; + +int open(const char *pathname, int flags, ...) { com32sys_t regs; int fd; struct file_info *fp; - - if ( flags ) { - errno = EINVAL; - return -1; - } - for ( fd = 0, fp = __file_info ; fd < NFILES ; fd++, fp++ ) - if ( fp->blocklg2 == 0 ) - break; + fd = opendev(&file_dev, flags); - if ( fd >= NFILES ) { - errno = EMFILE; + if ( fd < 0 ) return -1; - } + + fp = &__file_info[fd]; strlcpy(__com32.cs_bounce, pathname, __com32.cs_bounce_size); @@ -67,13 +80,13 @@ int open(const char *pathname, int flags, mode_t mode) { uint16_t blklg2; asm("bsrw %1,%0" : "=r" (blklg2) : "rm" (regs.ecx.w[0])); - fp->blocklg2 = blklg2; + fp->p.f.blocklg2 = blklg2; } - fp->length = regs.eax.l; - fp->filedes = regs.esi.w[0]; - fp->offset = 0; - fp->nbytes = 0; - fp->datap = fp->buf; + fp->p.f.length = regs.eax.l; + fp->p.f.filedes = regs.esi.w[0]; + fp->p.f.offset = 0; + fp->p.f.nbytes = 0; + fp->p.f.datap = fp->p.f.buf; return fd; } diff --git a/com32/lib/sys/openconsole.c b/com32/lib/sys/openconsole.c new file mode 100644 index 0000000..08b584a --- /dev/null +++ b/com32/lib/sys/openconsole.c @@ -0,0 +1,52 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * openconsole.c + * + * Open the chosen console device + */ + +#include +#include +#include + +int openconsole(const struct dev_info *dev) +{ + close(0); + if ( opendev(dev, O_RDONLY) != 0 ) + return -1; + close(1); + if ( opendev(dev, O_WRONLY) != 1 ) + return -1; + close(2); + if ( opendev(dev, O_WRONLY) != 2 ) + return -1; + + return 0; +} diff --git a/com32/lib/sys/opendev.c b/com32/lib/sys/opendev.c new file mode 100644 index 0000000..0d49a95 --- /dev/null +++ b/com32/lib/sys/opendev.c @@ -0,0 +1,62 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include +#include +#include +#include "file.h" + +/* + * opendev.c + * + * Open a special device + */ + +int opendev(const struct dev_info *dev, int flags) +{ + int fd; + struct file_info *fp; + + if ( !(flags & 3) || (flags & ~dev->fileflags) ) { + errno = EINVAL; + return -1; + } + + for ( fd = 0, fp = __file_info ; fd < NFILES ; fd++, fp++ ) + if ( !fp->ops ) + break; + + if ( fd >= NFILES ) { + errno = EMFILE; + return -1; + } + + fp->ops = dev; + + return fd; +} diff --git a/com32/lib/sys/read.c b/com32/lib/sys/read.c index 1c16ce4..ea5fde3 100644 --- a/com32/lib/sys/read.c +++ b/com32/lib/sys/read.c @@ -29,64 +29,29 @@ /* * read.c * - * Reading from a file + * Reading from a file descriptor */ #include #include #include #include +#include #include "file.h" ssize_t read(int fd, void *buf, size_t count) { - com32sys_t ireg, oreg; struct file_info *fp = &__file_info[fd]; - char *bufp = buf; - size_t n = 0; - size_t ncopy; - if ( fd >= NFILES || fp->blocklg2 == 0 ) { + if ( fd >= NFILES || !fp->ops ) { errno = EBADF; return -1; } - memset(&ireg, 0, sizeof ireg); - ireg.eax.w[0] = 0x0007; /* Read file */ - ireg.esi.w[0] = OFFS(__com32.cs_bounce); - ireg.es = SEG(__com32.cs_bounce); - - while ( count ) { - if ( fp->nbytes == 0 ) { - if ( fp->offset >= fp->length || !fp->filedes ) - return n; /* As good as it gets... */ - - ireg.esi.w[0] = fp->filedes; - ireg.ecx.w[0] = MAXBLOCK >> fp->blocklg2; - - __intcall(0x22, &ireg, &oreg); - - if ( oreg.eflags.l & EFLAGS_CF ) { - errno = EIO; - return -1; - } - - fp->filedes = ireg.esi.w[0]; - fp->nbytes = min(fp->length-fp->offset, (unsigned)MAXBLOCK); - fp->datap = fp->buf; - memcpy(fp->buf, __com32.cs_bounce, fp->nbytes); - } - - ncopy = min(count, fp->nbytes); - memcpy(bufp, fp->datap, ncopy); - - n += ncopy; - bufp += ncopy; - count -= ncopy; - fp->datap += ncopy; - fp->offset += ncopy; - fp->nbytes -= ncopy; + if ( __unlikely(!fp->ops->read) ) { + errno = EINVAL; + return -1; } - return n; + return fp->ops->read(fp, buf, count); } diff --git a/com32/lib/sys/stdcon.c b/com32/lib/sys/stdcon.c new file mode 100644 index 0000000..7a83592 --- /dev/null +++ b/com32/lib/sys/stdcon.c @@ -0,0 +1,53 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * stdcon.c + * + * Default console + */ + +#include +#include +#include +#include +#include +#include +#include "file.h" + +extern ssize_t __stdcon_read(struct file_info *, void *, size_t); +extern ssize_t __stdcon_write(struct file_info *, const void *, size_t); + +const struct dev_info dev_stdcon = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY, + .fileflags = O_RDWR|O_CREAT|O_TRUNC|O_APPEND, + .read = __stdcon_read, + .write = __stdcon_write, + .close = NULL, +}; diff --git a/com32/lib/sys/stdcon_read.c b/com32/lib/sys/stdcon_read.c new file mode 100644 index 0000000..0e5df19 --- /dev/null +++ b/com32/lib/sys/stdcon_read.c @@ -0,0 +1,68 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * stdcon_read.c + * + * Reading from the console, with echo + */ + +#include +#include +#include +#include +#include "file.h" + +ssize_t __stdcon_read(struct file_info *fp, void *buf, size_t count) +{ + com32sys_t ireg, oreg; + char *bufp = buf; + size_t n = 0; + + (void)fp; + + memset(&ireg, 0, sizeof ireg); + + while ( count ) { + ireg.eax.b[1] = 0x01; + __intcall(0x21, &ireg, &oreg); + *bufp++ = oreg.eax.b[0]; + n++; + + if ( ! --count ) + break; + + /* Only return more than one if there is stuff in the buffer */ + ireg.eax.b[1] = 0x0B; + __intcall(0x21, &ireg, &oreg); + if ( !oreg.eax.b[0] ) + break; + } + + return n; +} diff --git a/com32/lib/sys/stdcon_write.c b/com32/lib/sys/stdcon_write.c new file mode 100644 index 0000000..62bc4cc --- /dev/null +++ b/com32/lib/sys/stdcon_write.c @@ -0,0 +1,63 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * write.c + * + * Writing to the console + */ + +#include +#include +#include +#include +#include "file.h" + +ssize_t __stdcon_write(struct file_info *fp, const void *buf, size_t count) +{ + com32sys_t ireg; + const char *bufp = buf; + size_t n = 0; + + (void)fp; + + memset(&ireg, 0, sizeof ireg); + ireg.eax.b[1] = 0x02; + + while ( count-- ) { + if ( *bufp == '\n' ) { + ireg.edx.b[0] = '\r'; + __intcall(0x21, &ireg, NULL); + } + ireg.edx.b[0] = *bufp++; + __intcall(0x21, &ireg, NULL); + n++; + } + + return n; +} diff --git a/com32/lib/sys/write.c b/com32/lib/sys/write.c index b908f36..b4b3c6e 100644 --- a/com32/lib/sys/write.c +++ b/com32/lib/sys/write.c @@ -29,30 +29,29 @@ /* * write.c * - * Writing to the console + * Write to a file descriptor */ #include #include #include #include +#include #include "file.h" ssize_t write(int fd, void *buf, size_t count) { - com32sys_t ireg; struct file_info *fp = &__file_info[fd]; - char *bufp = buf; - size_t n = 0; - memset(&ireg, 0, sizeof ireg); - ireg.eax.b[1] = 0x02; + if ( fd >= NFILES || !fp->ops ) { + errno = EBADF; + return -1; + } - while ( count-- ) { - ireg.edx.b[0] = *bufp++; - __intcall(0x21, &ireg, NULL); - n++; + if ( __unlikely(!fp->ops->write) ) { + errno = EINVAL; + return -1; } - return n; + return fp->ops->write(fp, buf, count); } diff --git a/com32/modules/Makefile b/com32/modules/Makefile index a47e0a2..dfd6a3b 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -25,12 +25,13 @@ LD = ld -m elf_i386 AR = ar NASM = nasm RANLIB = ranlib -CFLAGS = -W -Wall -march=i386 -Os -fomit-frame-pointer -I../com32/include +CFLAGS = -W -Wall -march=i386 -Os -fomit-frame-pointer -I../include SFLAGS = -march=i386 LDFLAGS = -s -T ../lib/com32.ld OBJCOPY = objcopy PPMTOLSS16 = ../ppmtolss16 LIB = ../lib/libcom32.a +LIBGCC := $(shell $(CC) --print-libgcc) .SUFFIXES: .lss .c .o .elf .c32 @@ -46,7 +47,7 @@ all: hello.c32 .PRECIOUS: %.elf %.elf: %.o $(LIB) - $(LD) $(LDFLAGS) -o $@ $^ + $(LD) $(LDFLAGS) -o $@ $^ $(LIBGCC) %.c32: %.elf $(OBJCOPY) -O binary $< $@ diff --git a/com32/modules/hello.c b/com32/modules/hello.c index bcb018d..aea8766 100644 --- a/com32/modules/hello.c +++ b/com32/modules/hello.c @@ -17,11 +17,25 @@ * Hello, World! using libcom32 */ +#include #include +#include int main(void) { + char buffer[1024]; + + openconsole(&dev_stdcon); + printf("Hello, World!\n"); + for (;;) { + printf("> "); + fgets(buffer, sizeof buffer, stdin); + if ( !strncmp(buffer, "exit", 4) ) + break; + printf(": %s", buffer); + } + return 0; } -- 2.7.4