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 ([email protected]) 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 [email protected]
+ * 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