Module Name:    src
Committed By:   rin
Date:           Sat Jun 29 13:45:14 UTC 2024

Added Files:
        src/sys/arch/i386/stand/dosboot: dos_file.S doscommain.c dosfile.c
            dosfile.h start_dos.S
Removed Files:
        src/sys/arch/i386/stand/lib: dos_file.S dosfile.c dosfile.h
        src/sys/arch/i386/stand/lib/crt/dos: doscommain.c start_dos.S

Log Message:
i386: stand: Migrate DOS support routines from `lib` to `dosboot`


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/dosboot/dos_file.S \
    src/sys/arch/i386/stand/dosboot/doscommain.c \
    src/sys/arch/i386/stand/dosboot/dosfile.c \
    src/sys/arch/i386/stand/dosboot/dosfile.h \
    src/sys/arch/i386/stand/dosboot/start_dos.S
cvs rdiff -u -r1.6 -r0 src/sys/arch/i386/stand/lib/dos_file.S
cvs rdiff -u -r1.19 -r0 src/sys/arch/i386/stand/lib/dosfile.c
cvs rdiff -u -r1.4 -r0 src/sys/arch/i386/stand/lib/dosfile.h
cvs rdiff -u -r1.6 -r0 src/sys/arch/i386/stand/lib/crt/dos/doscommain.c
cvs rdiff -u -r1.10 -r0 src/sys/arch/i386/stand/lib/crt/dos/start_dos.S

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/sys/arch/i386/stand/dosboot/dos_file.S
diff -u /dev/null src/sys/arch/i386/stand/dosboot/dos_file.S:1.1
--- /dev/null	Sat Jun 29 13:45:14 2024
+++ src/sys/arch/i386/stand/dosboot/dos_file.S	Sat Jun 29 13:45:14 2024
@@ -0,0 +1,203 @@
+/*	$NetBSD: dos_file.S,v 1.1 2024/06/29 13:45:14 rin Exp $	*/
+	
+/* extracted from Tor Egge's patches for NetBSD boot */
+
+#include <machine/asm.h>
+
+/*
+# MSDOS call "INT 0x21 Function 0x3d" to open a file.
+# Call with	%ah = 0x3d
+# 		%al = 0x0  (access and sharing modes)
+#		%ds:%dx = ASCIZ filename
+#		%cl = attribute mask of files to look for
+*/
+
+	.globl _C_LABEL(doserrno)
+_C_LABEL(doserrno):	.long 1
+
+ENTRY(dosopen)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%edx
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	
+	movl	0x8(%ebp), %edx		# File name.
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	push	%ds
+	movl	%edx, %eax
+	shrl	$4, %eax
+	mov	%ds, %si
+	add	%si, %ax
+	mov	%ax, %ds
+	and	$0xf, %dx
+
+	movb	$0x3d, %ah		# Open existing file.
+	movb	$0x0 , %al		# ro
+
+	sti
+	int	$0x21
+	cli
+	pop	%ds
+
+	jnc	ok1
+	mov	%ax, _C_LABEL(doserrno)
+	movl	$-1, %edx
+	jmp err1
+ok1:
+	movl	$0,%edx
+	mov	%ax, %dx
+err1:
+	calll	_C_LABEL(real_to_prot) # back to protected mode
+	.code32
+
+	movl	%edx, %eax		# return value in %eax
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%edx
+	popl	%ebp
+	ret
+
+ENTRY(dosread)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+	pushl	%esi
+	pushl	%edi
+	
+	movl	0x8(%ebp), %ebx		# File handle
+	movl	0xc(%ebp), %edx		# Buffer.
+	movl	0x10(%ebp), %ecx	# Bytes to read
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	push	%ds
+	movl	%edx, %eax
+	shrl	$4, %eax
+	mov	%ds, %si
+	add	%si, %ax
+	mov	%ax, %ds
+	and	$0xf, %dx
+
+	movb	$0x3f, %ah		# Read from file or device
+
+	sti
+	int	$0x21
+	cli
+	pop	%ds
+
+	jnc	ok2
+	mov	%ax, _C_LABEL(doserrno)
+	movl	$-1, %edx
+	jmp	err2
+ok2:
+	movl	$0,%edx
+	mov	%ax, %dx
+err2:
+	calll	_C_LABEL(real_to_prot)	# back to protected mode
+	.code32
+
+	movl	%edx, %eax		# return value in %eax
+
+	popl	%edi
+	popl	%esi
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%ebp
+	ret
+
+ENTRY(dosclose)
+	.code32
+	pushl %ebp
+	movl  %esp, %ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	
+	movl	0x8(%ebp), %ebx		# File handle
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	movb	$0x3e, %ah		# Close file.
+
+	sti
+	int	$0x21
+	cli
+
+	jnc	ok3
+	mov	%ax, _C_LABEL(doserrno)
+	movl	$-1, %ebx
+	jmp	err3
+ok3:
+	movl	$0, %ebx
+err3:
+	calll	_C_LABEL(real_to_prot) # back to protected mode
+	.code32
+
+	movl	%ebx, %eax		# return value in %eax
+
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+
+ENTRY(dosseek)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+	pushl	%esi
+	pushl	%edi
+	
+	movl	0x8(%ebp), %ebx		# File handle
+	movl	0xc(%ebp), %ecx		# Offset
+	movl	0x10(%ebp) , %edx	# whence
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	movb	$0x42, %ah		# Seek
+	movb	%dl, %al		# whence
+	mov	%cx, %dx		#offs lo
+	shrl	$0x10, %ecx		#offs hi
+
+	sti
+	int	$0x21
+	cli
+
+	jnc	ok4
+	mov	%ax, _C_LABEL(doserrno)
+	movl	$-1, %edx
+	jmp	err4
+ok4:
+	shll	$0x10, %edx	#new ofs hi
+	mov	%ax, %dx	#new ofs lo
+err4:
+	calll	_C_LABEL(real_to_prot) # back to protected mode
+	.code32
+
+	movl	%edx, %eax		# return value in %eax
+
+	popl	%edi
+	popl	%esi
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%ebp
+	ret
Index: src/sys/arch/i386/stand/dosboot/doscommain.c
diff -u /dev/null src/sys/arch/i386/stand/dosboot/doscommain.c:1.1
--- /dev/null	Sat Jun 29 13:45:14 2024
+++ src/sys/arch/i386/stand/dosboot/doscommain.c	Sat Jun 29 13:45:14 2024
@@ -0,0 +1,119 @@
+/*	$NetBSD: doscommain.c,v 1.1 2024/06/29 13:45:14 rin Exp $	*/
+
+/*
+ * Copyright (c) 1996
+ *	Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* argument line processing for DOS .COM programs */
+
+#include <lib/libsa/stand.h>
+
+/* The Program Segment Prefix */
+
+static struct psp{
+	char mist1[0x2c];
+	short envseg;
+	char mist2[0x80-2-0x2c];
+	char cmdlen;
+	char cmd[127];
+} *PSP = (struct psp*)0;
+
+static char* argv[64]; /* theor max */
+
+static int whitespace(char);
+
+static int
+whitespace(char c)
+{
+	if ((c == '\0') || (c == ' ') || (c == '\t')
+	    || (c == '\r') || (c == '\n'))
+		return (1);
+	return 0;
+}
+
+enum state {skipping, doing_arg, doing_long_arg};
+
+/* build argv/argc, start real main() */
+int doscommain(void);
+extern int main(int, char**);
+
+int
+doscommain(void)
+{
+	int argc, i;
+	enum state s;
+
+	argv[0] = "???"; /* we don't know */
+	argc = 1;
+	s = skipping;
+
+	for (i = 0; i < PSP->cmdlen; i++){
+
+		if (whitespace(PSP->cmd[i])) {
+			if (s == doing_arg) {
+				/* end of argument word */
+				PSP->cmd[i] = '\0';
+				s = skipping;
+			}
+			continue;
+		}
+
+		if (PSP->cmd[i] == '"') {
+			/* start or end long arg
+			 * (end only if next char is whitespace)
+			 *  XXX but '" ' cannot be in argument
+			 */
+			switch (s) {
+			case skipping:
+				/* next char begins new argument word */
+				argv[argc++] = &PSP->cmd[i + 1];
+				s = doing_long_arg;
+				break;
+			case doing_long_arg:
+				if (whitespace(PSP->cmd[i + 1])) {
+					PSP->cmd[i] = '\0';
+					s = skipping;
+				}
+			case doing_arg:
+				/* ignore in the middle of arguments */
+			default:
+				break;
+			}
+			continue;
+		}
+
+		/* all other characters */
+		if (s == skipping) {
+			/* begin new argument word */
+			argv[argc++] = &PSP->cmd[i];
+			s = doing_arg;
+		}
+	}
+	if (s != skipping)
+		PSP->cmd[i] = '\0'; /* to be sure */
+
+	/* start real main() */
+	return main(argc, argv);
+}
Index: src/sys/arch/i386/stand/dosboot/dosfile.c
diff -u /dev/null src/sys/arch/i386/stand/dosboot/dosfile.c:1.1
--- /dev/null	Sat Jun 29 13:45:14 2024
+++ src/sys/arch/i386/stand/dosboot/dosfile.c	Sat Jun 29 13:45:14 2024
@@ -0,0 +1,241 @@
+/*	$NetBSD: dosfile.c,v 1.1 2024/06/29 13:45:14 rin Exp $	 */
+
+/*
+ * Copyright (c) 1996
+ *	Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * DOS filesystem for libsa
+ * standalone - uses no device, works only with DOS running
+ * needs lowlevel parts from dos_file.S
+ */
+
+#include <lib/libsa/stand.h>
+
+#include "diskbuf.h"
+#include "dosfile.h"
+
+extern int dosopen(const char *);
+extern void dosclose(int);
+extern int dosread(int, char *, int);
+extern int dosseek(int, int, int);
+
+struct dosfile {
+	int doshandle, off;
+};
+
+extern int doserrno;	/* in dos_file.S */
+
+static int dos2errno(void);
+
+static int
+dos2errno(void)
+{
+	int err;
+
+	switch (doserrno) {
+	    case 1: /* invalid function number */
+	    case 4: /* too many open files */
+	    case 12: /* invalid access mode */
+	    default:
+		err = EIO;
+		break;
+	    case 2: /* file not found */
+	    case 3: /* path not found */
+		err = ENOENT;
+		break;
+	    case 5: /* access denied */
+		err = EPERM;
+		break;
+	    case 6: /* invalid handle */
+		err = EINVAL;
+		break;
+	}
+	return err;
+}
+
+__compactcall int
+dos_open(const char *path, struct open_file *f)
+{
+	struct dosfile *df;
+
+	df = (struct dosfile *) alloc(sizeof(*df));
+	if (!df)
+		return -1;
+
+	df->off = 0;
+	df->doshandle = dosopen(path);
+	if (df->doshandle < 0) {
+#ifdef DEBUG
+		printf("DOS error %d\n", doserrno);
+#endif
+		dealloc(df, sizeof(*df));
+		return dos2errno();
+	}
+	f->f_fsdata = (void *) df;
+	return 0;
+}
+
+__compactcall int
+dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
+{
+	struct dosfile *df;
+	int             got;
+	static int      tc = 0;
+
+	df = (struct dosfile *) f->f_fsdata;
+
+	if (!(tc++ % 4))
+		twiddle();
+
+	if ((unsigned long) addr >= 0x10000) {
+		u_int           lsize = size;
+
+		while (lsize > 0) {
+			u_int           tsize;
+			size_t          tgot;
+			char		*p = addr;
+
+			tsize = lsize;
+
+			if (tsize > DISKBUFSIZE)
+				tsize = DISKBUFSIZE;
+
+			alloc_diskbuf(dos_read);
+
+			tgot = dosread(df->doshandle, diskbufp, tsize);
+			if (tgot < 0) {
+#ifdef DEBUG
+				printf("DOS error %d\n", doserrno);
+#endif
+				return dos2errno();
+			}
+			memcpy(p, diskbufp, tgot);
+
+			p += tgot;
+			lsize -= tgot;
+
+			if (tgot != tsize)
+				break;	/* EOF */
+		}
+		got = size - lsize;
+	} else {
+		got = dosread(df->doshandle, addr, size);
+
+		if (got < 0) {
+#ifdef DEBUG
+			printf("DOS error %d\n", doserrno);
+#endif
+			return dos2errno();
+		}
+	}
+
+	df->off += got;
+	size -= got;
+
+	if (resid)
+		*resid = size;
+	return 0;
+}
+
+__compactcall int
+dos_close(struct open_file *f)
+{
+	struct dosfile *df;
+	df = (struct dosfile *) f->f_fsdata;
+
+	dosclose(df->doshandle);
+
+	if (df)
+		dealloc(df, sizeof(*df));
+	return 0;
+}
+
+__compactcall int
+dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+	return EROFS;
+}
+
+__compactcall int
+dos_stat(struct open_file *f, struct stat *sb)
+{
+	sb->st_mode = 0444;
+	sb->st_nlink = 1;
+	sb->st_uid = 0;
+	sb->st_gid = 0;
+	sb->st_size = -1;
+	return 0;
+}
+
+__compactcall off_t
+dos_seek(struct open_file *f, off_t offset, int where)
+{
+	struct dosfile *df;
+	int             doswhence, res;
+#ifdef DOS_CHECK
+	int             checkoffs;
+#endif
+	df = (struct dosfile *) f->f_fsdata;
+
+	switch (where) {
+	case SEEK_SET:
+		doswhence = 0;
+#ifdef DOS_CHECK
+		checkoffs = offset;	/* don't trust DOS */
+#endif
+		break;
+	case SEEK_CUR:
+		doswhence = 1;
+#ifdef DOS_CHECK
+		checkoffs = df->off + offset;
+#endif
+		break;
+	case SEEK_END:
+		doswhence = 2;
+#ifdef DOS_CHECK
+		checkoffs = -1;	/* we dont know len */
+#endif
+		break;
+	default:
+		errno = EOFFSET;
+		return -1;
+	}
+	res = dosseek(df->doshandle, offset, doswhence);
+	if (res == -1) {
+		errno = dos2errno();
+		return -1;
+	}
+#ifdef DOS_CHECK
+	if ((checkoffs != -1) && (res != checkoffs)) {
+		printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
+		       df->off, offset, where, res);
+		errno = EOFFSET;
+		return -1;
+	}
+#endif
+	df->off = res;
+	return res;
+}
Index: src/sys/arch/i386/stand/dosboot/dosfile.h
diff -u /dev/null src/sys/arch/i386/stand/dosboot/dosfile.h:1.1
--- /dev/null	Sat Jun 29 13:45:14 2024
+++ src/sys/arch/i386/stand/dosboot/dosfile.h	Sat Jun 29 13:45:14 2024
@@ -0,0 +1,29 @@
+/*	$NetBSD: dosfile.h,v 1.1 2024/06/29 13:45:14 rin Exp $	*/
+
+/*
+ * Copyright (c) 1996
+ *	Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+FS_DEF(dos);
Index: src/sys/arch/i386/stand/dosboot/start_dos.S
diff -u /dev/null src/sys/arch/i386/stand/dosboot/start_dos.S:1.1
--- /dev/null	Sat Jun 29 13:45:14 2024
+++ src/sys/arch/i386/stand/dosboot/start_dos.S	Sat Jun 29 13:45:14 2024
@@ -0,0 +1,620 @@
+/*	$NetBSD: start_dos.S,v 1.1 2024/06/29 13:45:14 rin Exp $	*/
+	
+/*
+ * startup for DOS .COM programs
+ * with input from:
+ * netbsd:sys/arch/i386/boot/start.S
+ * Tor Egge's patches for NetBSD boot (pr port-i386/1002)
+ * freebsd:sys/i386/boot/netboot/start2.S
+ * XMS support by Martin Husemann
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (jul...@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  software.distribut...@cs.cmu.edu
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992 
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+
+
+CR0_PE		=	0x1
+
+	.data
+	.globl _C_LABEL(ourseg)
+_C_LABEL(ourseg):
+	.long	0
+
+/**************************************************************************
+GLOBAL DESCRIPTOR TABLE
+**************************************************************************/
+#ifdef __ELF__
+	.align	16
+#else
+	.align	4
+#endif
+gdt:
+	.word	0, 0
+	.byte	0, 0x00, 0x00, 0
+
+#ifdef SUPPORT_LINUX	/* additional dummy */
+	.word	0, 0
+	.byte	0, 0x00, 0x00, 0
+#endif
+
+	/* kernel code segment */
+	.globl flatcodeseg
+flatcodeseg = . - gdt
+	.word	0xffff, 0
+	.byte	0, 0x9f, 0xcf, 0
+
+	/* kernel data segment */
+	.globl flatdataseg
+flatdataseg = . - gdt
+	.word	0xffff, 0
+	.byte	0, 0x93, 0xcf, 0
+
+	/* boot code segment, base will be patched */
+bootcodeseg = . - gdt
+	.word	0xffff, 0
+	.byte	0, 0x9e, 0x40, 0
+
+	/* boot data segment, base will be patched */
+bootdataseg = . - gdt
+#ifdef HEAP_BELOW_64K
+	.word	0xffff, 0
+	.byte	0, 0x92, 0x00, 0
+#else
+	.word	0xffff, 0
+	.byte	0, 0x92, 0x4f, 0
+#endif
+
+	/* 16 bit real mode, base will be patched */
+bootrealseg = . - gdt
+	.word	0xffff, 0
+	.byte	0, 0x9e, 0x00, 0
+
+	/* limits (etc) for data segment in real mode */
+bootrealdata = . - gdt
+	.word	0xffff, 0
+	.byte	0, 0x92, 0x00, 0
+gdtlen = . - gdt
+
+#ifdef __ELF__
+	.align	16
+#else
+	.align	4
+#endif
+gdtarg:
+	.word	gdtlen-1		/* limit */
+	.long	0			/* addr, will be inserted */
+
+	.text
+ENTRY(start)
+	.code16
+
+	# Check we are in real mode
+	movl	%cr0, %eax
+	testl	$CR0_PE, %eax
+	jz	2f
+	mov	$1f, %si
+	call	message
+	ret
+1:	.asciz	"must be in real mode\r\n"
+2:
+
+	xorl	%eax, %eax
+	mov	%cs, %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+	movl	%eax, _C_LABEL(ourseg)
+#ifdef STACK_START
+	add	$STACK_START / 16, %ax
+	mov	%ax, %ss
+	mov	$0xfffc, %sp
+#endif
+
+	/* fix up GDT entries for bootstrap */
+#define FIXUP(gdt_index) \
+	movw	%ax, gdt+gdt_index+2;	\
+	movb	%bl, gdt+gdt_index+4
+
+	mov	%cs, %ax
+	shll	$4, %eax
+	shldl	$16, %eax, %ebx
+	FIXUP(bootcodeseg)
+	FIXUP(bootrealseg)
+	FIXUP(bootdataseg)
+
+	/* fix up GDT pointer */
+	addl	$gdt, %eax
+	movl	%eax, gdtarg+2
+
+	/* change to protected mode */
+	calll	_C_LABEL(real_to_prot)
+	.code32
+
+	/* clear the bss */
+	movl	$_C_LABEL(edata), %edi
+	movl	$_C_LABEL(end), %ecx
+	subl	%edi, %ecx
+	xorb	%al, %al
+	rep
+	stosb
+
+	call	_C_LABEL(doscommain)
+ENTRY(_rtt)
+	call	_C_LABEL(prot_to_real)
+	.code16
+ENTRY(exit16)
+	sti
+	movb	$0x4c, %ah		/* return */
+	int	$0x21
+
+/*
+ * real_to_prot()
+ * 	transfer from real mode to protected mode.
+ */
+ENTRY(real_to_prot)
+	.code16
+	pushl	%eax
+	# guarantee that interrupt is disabled when in prot mode
+	cli
+
+	# load the gdtr
+	lgdtl	%cs:gdtarg
+
+	# set the PE bit of CR0
+	movl	%cr0, %eax
+	orl	$CR0_PE, %eax
+	movl	%eax, %cr0 
+
+	# make intrasegment jump to flush the processor pipeline and
+	# reload CS register
+	ljmp	$bootcodeseg, $xprot
+
+xprot:
+	.code32
+	# we are in USE32 mode now
+	# set up the protected mode segment registers : DS, SS, ES
+	movl	$bootdataseg, %eax
+	mov	%ax, %ds
+	mov	%ax, %es
+	mov	%ax, %ss
+#ifdef STACK_START
+	addl	$STACK_START, %esp
+#endif
+
+	popl	%eax
+	ret
+
+/*
+ * prot_to_real()
+ * 	transfer from protected mode to real mode
+ */
+ENTRY(prot_to_real)
+	.code32
+	pushl	%eax
+	# set up a dummy stack frame for the second seg change.
+	# Adjust the intersegment jump instruction following 
+	# the clearing of protected mode bit.
+	# This is self-modifying code, but we need a writable
+	# code segment, and an intersegment return does not give us that.
+
+	movl	_C_LABEL(ourseg), %eax
+	movw	%ax, xreal-2
+
+	/*
+	 * Load the segment registers while still in protected mode.
+	 * Otherwise the control bits don't get changed.
+	 * The correct values are loaded later.
+	 */
+	movw	$bootrealdata, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %ss
+
+	# Change to use16 mode.
+	ljmp	$bootrealseg, $x16
+
+x16:
+	.code16
+	# clear the PE bit of CR0
+	movl	%cr0, %eax
+	andl 	$~CR0_PE, %eax
+	movl	%eax, %cr0
+
+	# Here we have an 16 bits intersegment jump.
+	ljmp	$0, $xreal		/* segment patched above */
+
+xreal:
+	# we are in real mode now
+	# set up the real mode segment registers : DS, SS, ES
+	mov	%cs, %ax
+	mov	%ax, %ds
+	mov	%ax, %es
+#ifdef STACK_START
+	add	$STACK_START / 16, %ax
+	mov	%ax, %ss
+	subl	$STACK_START, %esp
+#else
+	mov	%ax, %ss
+#endif
+	push	%bp
+	movw	%sp, %bp
+	/* check we are returning to an address below 64k */
+	movw	2/*bp*/ + 4/*eax*/ + 2(%bp), %ax	/* high bits ret addr */
+	test	%ax, %ax
+	jne	1f
+	pop	%bp
+
+	sti
+	popl	%eax
+	retl
+
+1:	movw	$2f, %si
+	call	message
+	movl	2/*bp*/ + 4/*eax*/(%bp), %eax		/*  return address */
+	call	dump_eax
+	jmp	exit16
+2:	.asciz  "prot_to_real can't return to "
+
+
+/**************************************************************************
+___MAIN - Dummy to keep GCC happy
+**************************************************************************/
+ENTRY(__main)
+	ret
+
+/*
+ * pbzero(dst, cnt)
+ *	where dst is a physical address and cnt is the length
+ */
+ENTRY(pbzero)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%es
+	pushl	%edi
+
+	cld
+
+	# set %es to point at the flat segment
+	movl	$flatdataseg, %eax
+	mov	%ax, %es
+
+	movl	8(%ebp), %edi		# destination
+	movl	12(%ebp), %ecx		# count
+	xorl	%eax, %eax		# value
+
+	rep
+	stosb
+
+	popl	%edi
+	popl	%es
+	popl	%ebp
+	ret
+
+/*
+ * vpbcopy(src, dst, cnt)
+ *	where src is a virtual address and dst is a physical address
+ */
+ENTRY(vpbcopy)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%es
+	pushl	%esi
+	pushl	%edi
+
+	cld
+
+	# set %es to point at the flat segment
+	movl	$flatdataseg, %eax
+	mov	%ax, %es
+
+	movl	8(%ebp), %esi		# source
+	movl	12(%ebp), %edi		# destination
+	movl	16(%ebp), %ecx		# count
+
+	rep
+	movsb
+
+	popl	%edi
+	popl	%esi
+	popl	%es
+	popl	%ebp
+	ret
+
+/*
+ * pvbcopy(src, dst, cnt)
+ *	where src is a physical address and dst is a virtual address
+ */
+ENTRY(pvbcopy)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ds
+	pushl	%esi
+	pushl	%edi
+
+	cld
+
+	# set %ds to point at the flat segment
+	movl	$flatdataseg, %eax
+	mov	%ax, %ds
+
+	movl	8(%ebp), %esi		# source
+	movl	12(%ebp), %edi		# destination
+	movl	16(%ebp), %ecx		# count
+
+	rep
+	movsb
+
+	popl	%edi
+	popl	%esi
+	popl	%ds
+	popl	%ebp
+	ret
+
+ENTRY(vtophys)
+	.code32
+	movl	_C_LABEL(ourseg), %eax
+	shll	$4, %eax
+	addl	4(%esp), %eax
+	ret
+
+message:
+	.code16
+	pushal
+message_1:
+	cld
+1:	lodsb
+	testb	%al, %al
+	jz	2f
+	movb	$0xe, %ah
+	movw	$1, %bx
+	int	$0x10
+	jmp	1b
+
+2:	movb	$0x86, %ah
+	mov	$16, %cx
+	int	$0x15			/* delay about a second */
+	popal
+	ret
+
+/* These are useful for debugging
+ */
+	.data
+eax_buf:
+	.long	0, 0, 0, 0
+	.text
+ENTRY(dump_eax)
+	.code16
+	pushal
+	movw	$eax_buf, %si
+	mov	%si, %di
+	movw	$8, %cx
+1:	roll	$4, %eax
+	mov	%ax, %bx
+	andb	$0x0f, %al
+	addb	$0x30, %al			/* 30..3f - clear AF */
+#if 1 /* 5 bytes to generate real hex... */
+	daa					/* 30..39, 40..45 */
+	addb	$0xc0, %al			/* f0..f9, 00..05 */
+	adcb	$0x40, %al			/* 30..39, 41..45 */
+#endif
+	movb	%al, (%di)			/* %es != %ds, so can't ... */
+	inc	%di				/* ... use stosb */
+	mov	%bx, %ax
+	loop	1b
+	movw	$0x20, %ax			/* space + null */
+	movw	%ax, (%di)
+	jmp	message_1
+
+	.globl	_C_LABEL(trace_word)
+_C_LABEL(trace_word):
+	.code32
+	movl	4(%esp), %edx
+
+	call	_C_LABEL(prot_to_real)
+	.code16
+	movl	%edx, %eax
+	call	dump_eax
+	calll	_C_LABEL(real_to_prot)
+	.code32
+	ret
+
+	.globl	_C_LABEL(trace_str)
+_C_LABEL(trace_str):
+	.code32
+	pushl	%esi
+
+	call	_C_LABEL(prot_to_real)
+	.code16
+	mov	%sp, %si
+	mov	8(%si), %si
+	call	message
+	calll	_C_LABEL(real_to_prot)
+	.code32
+	popl	%esi
+	ret
+
+#ifdef XMS
+
+/* pointer to XMS driver, 0 if no XMS used */
+
+	.data
+_C_LABEL(xmsdrv):
+	.long	0
+
+	.text
+ENTRY(checkxms)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%edx
+	pushl	%es
+	pushl	%esi
+	pushl	%edi
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	movw	$0x4300, %ax
+	int	$0x2f			/* check if XMS installed */
+	cmpb	$0x80, %al
+	jnz	noxms
+
+	movw	$0x4310, %ax
+	int	$0x2f			/* get driver address */
+
+	movw	%bx, _C_LABEL(xmsdrv)	/* save es:bx to _xmsdrv */
+	movw	%es, _C_LABEL(xmsdrv) + 2
+
+	movb	$0x08, %ah		/* XMS: query free extended memory */
+#if 0
+	movb	$0x00, %bl
+#endif
+	lcall	*_C_LABEL(xmsdrv)
+	jmp	xdone
+
+noxms:		/* no XMS manager found */
+	mov	$0, %dx
+
+xdone:
+	calll	_C_LABEL(real_to_prot) # back to protected mode
+	.code32
+
+	xorl	%eax, %eax
+	movw	%dx, %ax
+
+	popl	%edi
+	popl	%esi
+	popl	%es
+	popl	%edx
+	popl	%ebx
+	popl	%ebp
+	ret
+
+/*
+	Allocate a block of XMS memory with the requested size
+		void *xmsalloc(long int kBytes);
+
+	Depends on _xmsdrv being set by getextmem() before first call
+	to this function.
+
+	Return value: a physical address.
+*/
+ENTRY(xmsalloc)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%edx
+	pushl	%esi
+	pushl	%edi
+
+	movl	0x8(%ebp), %edx # Kbytes needed
+
+	call	_C_LABEL(prot_to_real)	# enter real mode
+	.code16
+
+	movb	$0x09, %ah		# XMS allocate block
+	lcall	*_C_LABEL(xmsdrv)	# result: handle in %dx
+	movb	$0x0c, %ah		# XMS lock block
+	lcall	*_C_LABEL(xmsdrv)	# result: 32 bit physical addr in DX:BX
+
+	calll	_C_LABEL(real_to_prot) # back to protected mode
+	.code32
+
+	movl	%edx, %eax
+	shl	$16, %eax
+	movw	%bx, %ax	# result in %eax
+
+	popl	%edi
+	popl	%esi
+	popl	%edx
+	popl	%ebx
+	popl	%ebp
+	ret
+
+/*
+ * ppbcopy(src, dst, cnt)
+ *	where src and dst are physical addresses
+ */
+ENTRY(ppbcopy)
+	.code32
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%es
+	pushl	%esi
+	pushl	%edi
+
+	cld
+
+	# set %es to point at the flat segment
+	movl	$flatdataseg, %eax
+	mov	%ax, %es
+
+	movl	8(%ebp), %esi		# source
+	movl	12(%ebp), %edi		# destination
+	movl	16(%ebp), %ecx		# count
+
+	es
+	rep
+	movsb
+
+	popl	%edi
+	popl	%esi
+	popl	%es
+	popl	%ebp
+	ret
+
+#endif

Reply via email to