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