1 /* $NetBSD: start_dos.S,v 1.10 2010/12/20 01:12:44 jakllsch Exp $ */
4 * startup for DOS .COM programs
6 * netbsd:sys/arch/i386/boot/start.S
7 * Tor Egge's patches for NetBSD boot (pr port-i386/1002)
8 * freebsd:sys/i386/boot/netboot/start2.S
9 * XMS support by Martin Husemann
13 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
15 * Mach Operating System
16 * Copyright (c) 1992, 1991 Carnegie Mellon University
17 * All Rights Reserved.
19 * Permission to use, copy, modify and distribute this software and its
20 * documentation is hereby granted, provided that both the copyright
21 * notice and this permission notice appear in all copies of the
22 * software, derivative works or modified versions, and any portions
23 * thereof, and that both notices appear in supporting documentation.
25 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
26 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
27 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
29 * Carnegie Mellon requests users of this software to return to
31 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
32 * School of Computer Science
33 * Carnegie Mellon University
34 * Pittsburgh PA 15213-3890
36 * any improvements or extensions that they make and grant Carnegie Mellon
37 * the rights to redistribute these changes.
41 Copyright 1988, 1989, 1990, 1991, 1992
42 by Intel Corporation, Santa Clara, California.
46 Permission to use, copy, modify, and distribute this software and
47 its documentation for any purpose and without fee is hereby
48 granted, provided that the above copyright notice appears in all
49 copies and that both the copyright notice and this permission notice
50 appear in supporting documentation, and that the name of Intel
51 not be used in advertising or publicity pertaining to distribution
52 of the software without specific, written prior permission.
54 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
55 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
56 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
57 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
58 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
59 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
60 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
63 #include <machine/asm.h>
69 .globl _C_LABEL(ourseg)
73 /**************************************************************************
74 GLOBAL DESCRIPTOR TABLE
75 **************************************************************************/
83 .byte 0, 0x00, 0x00, 0
85 #ifdef SUPPORT_LINUX /* additional dummy */
87 .byte 0, 0x00, 0x00, 0
90 /* kernel code segment */
94 .byte 0, 0x9f, 0xcf, 0
96 /* kernel data segment */
100 .byte 0, 0x93, 0xcf, 0
102 /* boot code segment, base will be patched */
103 bootcodeseg = . - gdt
105 .byte 0, 0x9e, 0x40, 0
107 /* boot data segment, base will be patched */
108 bootdataseg = . - gdt
109 #ifdef HEAP_BELOW_64K
111 .byte 0, 0x92, 0x00, 0
114 .byte 0, 0x92, 0x4f, 0
117 /* 16 bit real mode, base will be patched */
118 bootrealseg = . - gdt
120 .byte 0, 0x9e, 0x00, 0
122 /* limits (etc) for data segment in real mode */
123 bootrealdata = . - gdt
125 .byte 0, 0x92, 0x00, 0
134 .word gdtlen-1 /* limit */
135 .long 0 /* addr, will be inserted */
141 # Check we are in real mode
148 1: .asciz "must be in real mode\r\n"
155 movl %eax, _C_LABEL(ourseg)
157 add $STACK_START / 16, %ax
162 /* fix up GDT entries for bootstrap */
163 #define FIXUP(gdt_index) \
164 movw %ax, gdt+gdt_index+2; \
165 movb %bl, gdt+gdt_index+4
169 shldl $16, %eax, %ebx
174 /* fix up GDT pointer */
178 /* change to protected mode */
179 calll _C_LABEL(real_to_prot)
183 movl $_C_LABEL(edata), %edi
184 movl $_C_LABEL(end), %ecx
190 call _C_LABEL(doscommain)
192 call _C_LABEL(prot_to_real)
196 movb $0x4c, %ah /* return */
201 * transfer from real mode to protected mode.
206 # guarantee that interrupt is disabled when in prot mode
212 # set the PE bit of CR0
217 # make intrasegment jump to flush the processor pipeline and
219 ljmp $bootcodeseg, $xprot
223 # we are in USE32 mode now
224 # set up the protected mode segment registers : DS, SS, ES
225 movl $bootdataseg, %eax
230 addl $STACK_START, %esp
238 * transfer from protected mode to real mode
243 # set up a dummy stack frame for the second seg change.
244 # Adjust the intersegment jump instruction following
245 # the clearing of protected mode bit.
246 # This is self-modifying code, but we need a writable
247 # code segment, and an intersegment return does not give us that.
249 movl _C_LABEL(ourseg), %eax
253 * Load the segment registers while still in protected mode.
254 * Otherwise the control bits don't get changed.
255 * The correct values are loaded later.
257 movw $bootrealdata, %ax
262 # Change to use16 mode.
263 ljmp $bootrealseg, $x16
267 # clear the PE bit of CR0
272 # Here we have an 16 bits intersegment jump.
273 ljmp $0, $xreal /* segment patched above */
276 # we are in real mode now
277 # set up the real mode segment registers : DS, SS, ES
282 add $STACK_START / 16, %ax
284 subl $STACK_START, %esp
290 /* check we are returning to an address below 64k */
291 movw 2/*bp*/ + 4/*eax*/ + 2(%bp), %ax /* high bits ret addr */
302 movl 2/*bp*/ + 4/*eax*/(%bp), %eax /* return address */
305 2: .asciz "prot_to_real can't return to "
308 /**************************************************************************
309 ___MAIN - Dummy to keep GCC happy
310 **************************************************************************/
316 * where dst is a physical address and cnt is the length
327 # set %es to point at the flat segment
328 movl $flatdataseg, %eax
331 movl 8(%ebp), %edi # destination
332 movl 12(%ebp), %ecx # count
333 xorl %eax, %eax # value
344 * vpbcopy(src, dst, cnt)
345 * where src is a virtual address and dst is a physical address
357 # set %es to point at the flat segment
358 movl $flatdataseg, %eax
361 movl 8(%ebp), %esi # source
362 movl 12(%ebp), %edi # destination
363 movl 16(%ebp), %ecx # count
375 * pvbcopy(src, dst, cnt)
376 * where src is a physical address and dst is a virtual address
388 # set %ds to point at the flat segment
389 movl $flatdataseg, %eax
392 movl 8(%ebp), %esi # source
393 movl 12(%ebp), %edi # destination
394 movl 16(%ebp), %ecx # count
407 movl _C_LABEL(ourseg), %eax
427 int $0x15 /* delay about a second */
431 /* These are useful for debugging
446 addb $0x30, %al /* 30..3f - clear AF */
447 #if 1 /* 5 bytes to generate real hex... */
448 daa /* 30..39, 40..45 */
449 addb $0xc0, %al /* f0..f9, 00..05 */
450 adcb $0x40, %al /* 30..39, 41..45 */
452 movb %al, (%di) /* %es != %ds, so can't ... */
453 inc %di /* ... use stosb */
456 movw $0x20, %ax /* space + null */
460 .globl _C_LABEL(trace_word)
461 _C_LABEL(trace_word):
465 call _C_LABEL(prot_to_real)
469 calll _C_LABEL(real_to_prot)
473 .globl _C_LABEL(trace_str)
478 call _C_LABEL(prot_to_real)
483 calll _C_LABEL(real_to_prot)
490 /* pointer to XMS driver, 0 if no XMS used */
507 call _C_LABEL(prot_to_real) # enter real mode
511 int $0x2f /* check if XMS installed */
516 int $0x2f /* get driver address */
518 movw %bx, _C_LABEL(xmsdrv) /* save es:bx to _xmsdrv */
519 movw %es, _C_LABEL(xmsdrv) + 2
521 movb $0x08, %ah /* XMS: query free extended memory */
525 lcall *_C_LABEL(xmsdrv)
528 noxms: /* no XMS manager found */
532 calll _C_LABEL(real_to_prot) # back to protected mode
547 Allocate a block of XMS memory with the requested size
548 void *xmsalloc(long int kBytes);
550 Depends on _xmsdrv being set by getextmem() before first call
553 Return value: a physical address.
564 movl 0x8(%ebp), %edx # Kbytes needed
566 call _C_LABEL(prot_to_real) # enter real mode
569 movb $0x09, %ah # XMS allocate block
570 lcall *_C_LABEL(xmsdrv) # result: handle in %dx
571 movb $0x0c, %ah # XMS lock block
572 lcall *_C_LABEL(xmsdrv) # result: 32 bit physical addr in DX:BX
574 calll _C_LABEL(real_to_prot) # back to protected mode
579 movw %bx, %ax # result in %eax
589 * ppbcopy(src, dst, cnt)
590 * where src and dst are physical addresses
602 # set %es to point at the flat segment
603 movl $flatdataseg, %eax
606 movl 8(%ebp), %esi # source
607 movl 12(%ebp), %edi # destination
608 movl 16(%ebp), %ecx # count