Home | History | Annotate | Line # | Download | only in dosboot
      1  1.2  andvar /*	$NetBSD: start_dos.S,v 1.2 2024/09/11 20:15:36 andvar Exp $	*/
      2  1.1     rin 
      3  1.1     rin /*
      4  1.1     rin  * startup for DOS .COM programs
      5  1.1     rin  * with input from:
      6  1.1     rin  * netbsd:sys/arch/i386/boot/start.S
      7  1.1     rin  * Tor Egge's patches for NetBSD boot (pr port-i386/1002)
      8  1.1     rin  * freebsd:sys/i386/boot/netboot/start2.S
      9  1.1     rin  */
     10  1.1     rin 
     11  1.1     rin /*
     12  1.1     rin  * Ported to boot 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
     13  1.1     rin  *
     14  1.1     rin  * Mach Operating System
     15  1.1     rin  * Copyright (c) 1992, 1991 Carnegie Mellon University
     16  1.1     rin  * All Rights Reserved.
     17  1.1     rin  *
     18  1.1     rin  * Permission to use, copy, modify and distribute this software and its
     19  1.1     rin  * documentation is hereby granted, provided that both the copyright
     20  1.1     rin  * notice and this permission notice appear in all copies of the
     21  1.1     rin  * software, derivative works or modified versions, and any portions
     22  1.1     rin  * thereof, and that both notices appear in supporting documentation.
     23  1.1     rin  *
     24  1.1     rin  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     25  1.1     rin  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     26  1.1     rin  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     27  1.1     rin  *
     28  1.1     rin  * Carnegie Mellon requests users of this software to return to
     29  1.1     rin  *
     30  1.1     rin  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     31  1.1     rin  *  School of Computer Science
     32  1.1     rin  *  Carnegie Mellon University
     33  1.1     rin  *  Pittsburgh PA 15213-3890
     34  1.1     rin  *
     35  1.1     rin  * any improvements or extensions that they make and grant Carnegie Mellon
     36  1.1     rin  * the rights to redistribute these changes.
     37  1.1     rin  */
     38  1.1     rin 
     39  1.1     rin /*
     40  1.1     rin   Copyright 1988, 1989, 1990, 1991, 1992
     41  1.1     rin    by Intel Corporation, Santa Clara, California.
     42  1.1     rin 
     43  1.1     rin                 All Rights Reserved
     44  1.1     rin 
     45  1.1     rin Permission to use, copy, modify, and distribute this software and
     46  1.1     rin its documentation for any purpose and without fee is hereby
     47  1.1     rin granted, provided that the above copyright notice appears in all
     48  1.1     rin copies and that both the copyright notice and this permission notice
     49  1.1     rin appear in supporting documentation, and that the name of Intel
     50  1.1     rin not be used in advertising or publicity pertaining to distribution
     51  1.1     rin of the software without specific, written prior permission.
     52  1.1     rin 
     53  1.1     rin INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     54  1.1     rin INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
     55  1.1     rin IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     56  1.1     rin CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     57  1.1     rin LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     58  1.1     rin NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     59  1.1     rin WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     60  1.1     rin */
     61  1.1     rin 
     62  1.1     rin #include <machine/asm.h>
     63  1.1     rin 
     64  1.1     rin 
     65  1.1     rin CR0_PE		=	0x1
     66  1.1     rin 
     67  1.1     rin 	.data
     68  1.1     rin 	.globl _C_LABEL(ourseg)
     69  1.1     rin _C_LABEL(ourseg):
     70  1.1     rin 	.long	0
     71  1.1     rin 
     72  1.1     rin /**************************************************************************
     73  1.1     rin GLOBAL DESCRIPTOR TABLE
     74  1.1     rin **************************************************************************/
     75  1.1     rin #ifdef __ELF__
     76  1.1     rin 	.align	16
     77  1.1     rin #else
     78  1.1     rin 	.align	4
     79  1.1     rin #endif
     80  1.1     rin gdt:
     81  1.1     rin 	.word	0, 0
     82  1.1     rin 	.byte	0, 0x00, 0x00, 0
     83  1.1     rin 
     84  1.1     rin #ifdef SUPPORT_LINUX	/* additional dummy */
     85  1.1     rin 	.word	0, 0
     86  1.1     rin 	.byte	0, 0x00, 0x00, 0
     87  1.1     rin #endif
     88  1.1     rin 
     89  1.1     rin 	/* kernel code segment */
     90  1.1     rin 	.globl flatcodeseg
     91  1.1     rin flatcodeseg = . - gdt
     92  1.1     rin 	.word	0xffff, 0
     93  1.1     rin 	.byte	0, 0x9f, 0xcf, 0
     94  1.1     rin 
     95  1.1     rin 	/* kernel data segment */
     96  1.1     rin 	.globl flatdataseg
     97  1.1     rin flatdataseg = . - gdt
     98  1.1     rin 	.word	0xffff, 0
     99  1.1     rin 	.byte	0, 0x93, 0xcf, 0
    100  1.1     rin 
    101  1.1     rin 	/* boot code segment, base will be patched */
    102  1.1     rin bootcodeseg = . - gdt
    103  1.1     rin 	.word	0xffff, 0
    104  1.1     rin 	.byte	0, 0x9e, 0x40, 0
    105  1.1     rin 
    106  1.1     rin 	/* boot data segment, base will be patched */
    107  1.1     rin bootdataseg = . - gdt
    108  1.1     rin #ifdef HEAP_BELOW_64K
    109  1.1     rin 	.word	0xffff, 0
    110  1.1     rin 	.byte	0, 0x92, 0x00, 0
    111  1.1     rin #else
    112  1.1     rin 	.word	0xffff, 0
    113  1.1     rin 	.byte	0, 0x92, 0x4f, 0
    114  1.1     rin #endif
    115  1.1     rin 
    116  1.1     rin 	/* 16 bit real mode, base will be patched */
    117  1.1     rin bootrealseg = . - gdt
    118  1.1     rin 	.word	0xffff, 0
    119  1.1     rin 	.byte	0, 0x9e, 0x00, 0
    120  1.1     rin 
    121  1.1     rin 	/* limits (etc) for data segment in real mode */
    122  1.1     rin bootrealdata = . - gdt
    123  1.1     rin 	.word	0xffff, 0
    124  1.1     rin 	.byte	0, 0x92, 0x00, 0
    125  1.1     rin gdtlen = . - gdt
    126  1.1     rin 
    127  1.1     rin #ifdef __ELF__
    128  1.1     rin 	.align	16
    129  1.1     rin #else
    130  1.1     rin 	.align	4
    131  1.1     rin #endif
    132  1.1     rin gdtarg:
    133  1.1     rin 	.word	gdtlen-1		/* limit */
    134  1.1     rin 	.long	0			/* addr, will be inserted */
    135  1.1     rin 
    136  1.1     rin 	.text
    137  1.1     rin ENTRY(start)
    138  1.1     rin 	.code16
    139  1.1     rin 
    140  1.1     rin 	# Check we are in real mode
    141  1.1     rin 	movl	%cr0, %eax
    142  1.1     rin 	testl	$CR0_PE, %eax
    143  1.1     rin 	jz	2f
    144  1.1     rin 	mov	$1f, %si
    145  1.1     rin 	call	message
    146  1.1     rin 	ret
    147  1.1     rin 1:	.asciz	"must be in real mode\r\n"
    148  1.1     rin 2:
    149  1.1     rin 
    150  1.1     rin 	xorl	%eax, %eax
    151  1.1     rin 	mov	%cs, %ax
    152  1.1     rin 	mov	%ax, %ds
    153  1.1     rin 	mov	%ax, %es
    154  1.1     rin 	movl	%eax, _C_LABEL(ourseg)
    155  1.1     rin #ifdef STACK_START
    156  1.1     rin 	add	$STACK_START / 16, %ax
    157  1.1     rin 	mov	%ax, %ss
    158  1.1     rin 	mov	$0xfffc, %sp
    159  1.1     rin #endif
    160  1.1     rin 
    161  1.1     rin 	/* fix up GDT entries for bootstrap */
    162  1.1     rin #define FIXUP(gdt_index) \
    163  1.1     rin 	movw	%ax, gdt+gdt_index+2;	\
    164  1.1     rin 	movb	%bl, gdt+gdt_index+4
    165  1.1     rin 
    166  1.1     rin 	mov	%cs, %ax
    167  1.1     rin 	shll	$4, %eax
    168  1.1     rin 	shldl	$16, %eax, %ebx
    169  1.1     rin 	FIXUP(bootcodeseg)
    170  1.1     rin 	FIXUP(bootrealseg)
    171  1.1     rin 	FIXUP(bootdataseg)
    172  1.1     rin 
    173  1.1     rin 	/* fix up GDT pointer */
    174  1.1     rin 	addl	$gdt, %eax
    175  1.1     rin 	movl	%eax, gdtarg+2
    176  1.1     rin 
    177  1.1     rin 	/* change to protected mode */
    178  1.1     rin 	calll	_C_LABEL(real_to_prot)
    179  1.1     rin 	.code32
    180  1.1     rin 
    181  1.1     rin 	/* clear the bss */
    182  1.1     rin 	movl	$_C_LABEL(edata), %edi
    183  1.1     rin 	movl	$_C_LABEL(end), %ecx
    184  1.1     rin 	subl	%edi, %ecx
    185  1.1     rin 	xorb	%al, %al
    186  1.1     rin 	rep
    187  1.1     rin 	stosb
    188  1.1     rin 
    189  1.1     rin 	call	_C_LABEL(doscommain)
    190  1.1     rin ENTRY(_rtt)
    191  1.1     rin 	call	_C_LABEL(prot_to_real)
    192  1.1     rin 	.code16
    193  1.1     rin ENTRY(exit16)
    194  1.1     rin 	sti
    195  1.1     rin 	movb	$0x4c, %ah		/* return */
    196  1.1     rin 	int	$0x21
    197  1.1     rin 
    198  1.1     rin /*
    199  1.1     rin  * real_to_prot()
    200  1.1     rin  * 	transfer from real mode to protected mode.
    201  1.1     rin  */
    202  1.1     rin ENTRY(real_to_prot)
    203  1.1     rin 	.code16
    204  1.1     rin 	pushl	%eax
    205  1.1     rin 	# guarantee that interrupt is disabled when in prot mode
    206  1.1     rin 	cli
    207  1.1     rin 
    208  1.1     rin 	# load the gdtr
    209  1.1     rin 	lgdtl	%cs:gdtarg
    210  1.1     rin 
    211  1.1     rin 	# set the PE bit of CR0
    212  1.1     rin 	movl	%cr0, %eax
    213  1.1     rin 	orl	$CR0_PE, %eax
    214  1.1     rin 	movl	%eax, %cr0
    215  1.1     rin 
    216  1.1     rin 	# make intrasegment jump to flush the processor pipeline and
    217  1.1     rin 	# reload CS register
    218  1.1     rin 	ljmp	$bootcodeseg, $xprot
    219  1.1     rin 
    220  1.1     rin xprot:
    221  1.1     rin 	.code32
    222  1.1     rin 	# we are in USE32 mode now
    223  1.1     rin 	# set up the protected mode segment registers : DS, SS, ES
    224  1.1     rin 	movl	$bootdataseg, %eax
    225  1.1     rin 	mov	%ax, %ds
    226  1.1     rin 	mov	%ax, %es
    227  1.1     rin 	mov	%ax, %ss
    228  1.1     rin #ifdef STACK_START
    229  1.1     rin 	addl	$STACK_START, %esp
    230  1.1     rin #endif
    231  1.1     rin 
    232  1.1     rin 	popl	%eax
    233  1.1     rin 	ret
    234  1.1     rin 
    235  1.1     rin /*
    236  1.1     rin  * prot_to_real()
    237  1.1     rin  * 	transfer from protected mode to real mode
    238  1.1     rin  */
    239  1.1     rin ENTRY(prot_to_real)
    240  1.1     rin 	.code32
    241  1.1     rin 	pushl	%eax
    242  1.1     rin 	# set up a dummy stack frame for the second seg change.
    243  1.1     rin 	# Adjust the intersegment jump instruction following
    244  1.1     rin 	# the clearing of protected mode bit.
    245  1.1     rin 	# This is self-modifying code, but we need a writable
    246  1.1     rin 	# code segment, and an intersegment return does not give us that.
    247  1.1     rin 
    248  1.1     rin 	movl	_C_LABEL(ourseg), %eax
    249  1.1     rin 	movw	%ax, xreal-2
    250  1.1     rin 
    251  1.1     rin 	/*
    252  1.1     rin 	 * Load the segment registers while still in protected mode.
    253  1.1     rin 	 * Otherwise the control bits don't get changed.
    254  1.1     rin 	 * The correct values are loaded later.
    255  1.1     rin 	 */
    256  1.1     rin 	movw	$bootrealdata, %ax
    257  1.1     rin 	movw	%ax, %ds
    258  1.1     rin 	movw	%ax, %es
    259  1.1     rin 	movw	%ax, %ss
    260  1.1     rin 
    261  1.1     rin 	# Change to use16 mode.
    262  1.1     rin 	ljmp	$bootrealseg, $x16
    263  1.1     rin 
    264  1.1     rin x16:
    265  1.1     rin 	.code16
    266  1.1     rin 	# clear the PE bit of CR0
    267  1.1     rin 	movl	%cr0, %eax
    268  1.1     rin 	andl 	$~CR0_PE, %eax
    269  1.1     rin 	movl	%eax, %cr0
    270  1.1     rin 
    271  1.1     rin 	# Here we have an 16 bits intersegment jump.
    272  1.1     rin 	ljmp	$0, $xreal		/* segment patched above */
    273  1.1     rin 
    274  1.1     rin xreal:
    275  1.1     rin 	# we are in real mode now
    276  1.1     rin 	# set up the real mode segment registers : DS, SS, ES
    277  1.1     rin 	mov	%cs, %ax
    278  1.1     rin 	mov	%ax, %ds
    279  1.1     rin 	mov	%ax, %es
    280  1.1     rin #ifdef STACK_START
    281  1.1     rin 	add	$STACK_START / 16, %ax
    282  1.1     rin 	mov	%ax, %ss
    283  1.1     rin 	subl	$STACK_START, %esp
    284  1.1     rin #else
    285  1.1     rin 	mov	%ax, %ss
    286  1.1     rin #endif
    287  1.1     rin 	push	%bp
    288  1.1     rin 	movw	%sp, %bp
    289  1.1     rin 	/* check we are returning to an address below 64k */
    290  1.1     rin 	movw	2/*bp*/ + 4/*eax*/ + 2(%bp), %ax	/* high bits ret addr */
    291  1.1     rin 	test	%ax, %ax
    292  1.1     rin 	jne	1f
    293  1.1     rin 	pop	%bp
    294  1.1     rin 
    295  1.1     rin 	sti
    296  1.1     rin 	popl	%eax
    297  1.1     rin 	retl
    298  1.1     rin 
    299  1.1     rin 1:	movw	$2f, %si
    300  1.1     rin 	call	message
    301  1.1     rin 	movl	2/*bp*/ + 4/*eax*/(%bp), %eax		/*  return address */
    302  1.1     rin 	call	dump_eax
    303  1.1     rin 	jmp	exit16
    304  1.1     rin 2:	.asciz  "prot_to_real can't return to "
    305  1.1     rin 
    306  1.1     rin 
    307  1.1     rin /**************************************************************************
    308  1.1     rin ___MAIN - Dummy to keep GCC happy
    309  1.1     rin **************************************************************************/
    310  1.1     rin ENTRY(__main)
    311  1.1     rin 	ret
    312  1.1     rin 
    313  1.1     rin /*
    314  1.1     rin  * pbzero(dst, cnt)
    315  1.1     rin  *	where dst is a physical address and cnt is the length
    316  1.1     rin  */
    317  1.1     rin ENTRY(pbzero)
    318  1.1     rin 	.code32
    319  1.1     rin 	pushl	%ebp
    320  1.1     rin 	movl	%esp, %ebp
    321  1.1     rin 	pushl	%es
    322  1.1     rin 	pushl	%edi
    323  1.1     rin 
    324  1.1     rin 	cld
    325  1.1     rin 
    326  1.1     rin 	# set %es to point at the flat segment
    327  1.1     rin 	movl	$flatdataseg, %eax
    328  1.1     rin 	mov	%ax, %es
    329  1.1     rin 
    330  1.1     rin 	movl	8(%ebp), %edi		# destination
    331  1.1     rin 	movl	12(%ebp), %ecx		# count
    332  1.1     rin 	xorl	%eax, %eax		# value
    333  1.1     rin 
    334  1.1     rin 	rep
    335  1.1     rin 	stosb
    336  1.1     rin 
    337  1.1     rin 	popl	%edi
    338  1.1     rin 	popl	%es
    339  1.1     rin 	popl	%ebp
    340  1.1     rin 	ret
    341  1.1     rin 
    342  1.1     rin /*
    343  1.1     rin  * vpbcopy(src, dst, cnt)
    344  1.1     rin  *	where src is a virtual address and dst is a physical address
    345  1.1     rin  */
    346  1.1     rin ENTRY(vpbcopy)
    347  1.1     rin 	.code32
    348  1.1     rin 	pushl	%ebp
    349  1.1     rin 	movl	%esp, %ebp
    350  1.1     rin 	pushl	%es
    351  1.1     rin 	pushl	%esi
    352  1.1     rin 	pushl	%edi
    353  1.1     rin 
    354  1.1     rin 	cld
    355  1.1     rin 
    356  1.1     rin 	# set %es to point at the flat segment
    357  1.1     rin 	movl	$flatdataseg, %eax
    358  1.1     rin 	mov	%ax, %es
    359  1.1     rin 
    360  1.1     rin 	movl	8(%ebp), %esi		# source
    361  1.1     rin 	movl	12(%ebp), %edi		# destination
    362  1.1     rin 	movl	16(%ebp), %ecx		# count
    363  1.1     rin 
    364  1.1     rin 	rep
    365  1.1     rin 	movsb
    366  1.1     rin 
    367  1.1     rin 	popl	%edi
    368  1.1     rin 	popl	%esi
    369  1.1     rin 	popl	%es
    370  1.1     rin 	popl	%ebp
    371  1.1     rin 	ret
    372  1.1     rin 
    373  1.1     rin /*
    374  1.1     rin  * pvbcopy(src, dst, cnt)
    375  1.1     rin  *	where src is a physical address and dst is a virtual address
    376  1.1     rin  */
    377  1.1     rin ENTRY(pvbcopy)
    378  1.1     rin 	.code32
    379  1.1     rin 	pushl	%ebp
    380  1.1     rin 	movl	%esp, %ebp
    381  1.1     rin 	pushl	%ds
    382  1.1     rin 	pushl	%esi
    383  1.1     rin 	pushl	%edi
    384  1.1     rin 
    385  1.1     rin 	cld
    386  1.1     rin 
    387  1.1     rin 	# set %ds to point at the flat segment
    388  1.1     rin 	movl	$flatdataseg, %eax
    389  1.1     rin 	mov	%ax, %ds
    390  1.1     rin 
    391  1.1     rin 	movl	8(%ebp), %esi		# source
    392  1.1     rin 	movl	12(%ebp), %edi		# destination
    393  1.1     rin 	movl	16(%ebp), %ecx		# count
    394  1.1     rin 
    395  1.1     rin 	rep
    396  1.1     rin 	movsb
    397  1.1     rin 
    398  1.1     rin 	popl	%edi
    399  1.1     rin 	popl	%esi
    400  1.1     rin 	popl	%ds
    401  1.1     rin 	popl	%ebp
    402  1.1     rin 	ret
    403  1.1     rin 
    404  1.1     rin ENTRY(vtophys)
    405  1.1     rin 	.code32
    406  1.1     rin 	movl	_C_LABEL(ourseg), %eax
    407  1.1     rin 	shll	$4, %eax
    408  1.1     rin 	addl	4(%esp), %eax
    409  1.1     rin 	ret
    410  1.1     rin 
    411  1.1     rin message:
    412  1.1     rin 	.code16
    413  1.1     rin 	pushal
    414  1.1     rin message_1:
    415  1.1     rin 	cld
    416  1.1     rin 1:	lodsb
    417  1.1     rin 	testb	%al, %al
    418  1.1     rin 	jz	2f
    419  1.1     rin 	movb	$0xe, %ah
    420  1.1     rin 	movw	$1, %bx
    421  1.1     rin 	int	$0x10
    422  1.1     rin 	jmp	1b
    423  1.1     rin 
    424  1.1     rin 2:	movb	$0x86, %ah
    425  1.1     rin 	mov	$16, %cx
    426  1.1     rin 	int	$0x15			/* delay about a second */
    427  1.1     rin 	popal
    428  1.1     rin 	ret
    429  1.1     rin 
    430  1.1     rin /* These are useful for debugging
    431  1.1     rin  */
    432  1.1     rin 	.data
    433  1.1     rin eax_buf:
    434  1.1     rin 	.long	0, 0, 0, 0
    435  1.1     rin 	.text
    436  1.1     rin ENTRY(dump_eax)
    437  1.1     rin 	.code16
    438  1.1     rin 	pushal
    439  1.1     rin 	movw	$eax_buf, %si
    440  1.1     rin 	mov	%si, %di
    441  1.1     rin 	movw	$8, %cx
    442  1.1     rin 1:	roll	$4, %eax
    443  1.1     rin 	mov	%ax, %bx
    444  1.1     rin 	andb	$0x0f, %al
    445  1.1     rin 	addb	$0x30, %al			/* 30..3f - clear AF */
    446  1.1     rin #if 1 /* 5 bytes to generate real hex... */
    447  1.1     rin 	daa					/* 30..39, 40..45 */
    448  1.1     rin 	addb	$0xc0, %al			/* f0..f9, 00..05 */
    449  1.1     rin 	adcb	$0x40, %al			/* 30..39, 41..45 */
    450  1.1     rin #endif
    451  1.1     rin 	movb	%al, (%di)			/* %es != %ds, so can't ... */
    452  1.1     rin 	inc	%di				/* ... use stosb */
    453  1.1     rin 	mov	%bx, %ax
    454  1.1     rin 	loop	1b
    455  1.1     rin 	movw	$0x20, %ax			/* space + null */
    456  1.1     rin 	movw	%ax, (%di)
    457  1.1     rin 	jmp	message_1
    458  1.1     rin 
    459  1.1     rin 	.globl	_C_LABEL(trace_word)
    460  1.1     rin _C_LABEL(trace_word):
    461  1.1     rin 	.code32
    462  1.1     rin 	movl	4(%esp), %edx
    463  1.1     rin 
    464  1.1     rin 	call	_C_LABEL(prot_to_real)
    465  1.1     rin 	.code16
    466  1.1     rin 	movl	%edx, %eax
    467  1.1     rin 	call	dump_eax
    468  1.1     rin 	calll	_C_LABEL(real_to_prot)
    469  1.1     rin 	.code32
    470  1.1     rin 	ret
    471  1.1     rin 
    472  1.1     rin 	.globl	_C_LABEL(trace_str)
    473  1.1     rin _C_LABEL(trace_str):
    474  1.1     rin 	.code32
    475  1.1     rin 	pushl	%esi
    476  1.1     rin 
    477  1.1     rin 	call	_C_LABEL(prot_to_real)
    478  1.1     rin 	.code16
    479  1.1     rin 	mov	%sp, %si
    480  1.1     rin 	mov	8(%si), %si
    481  1.1     rin 	call	message
    482  1.1     rin 	calll	_C_LABEL(real_to_prot)
    483  1.1     rin 	.code32
    484  1.1     rin 	popl	%esi
    485  1.1     rin 	ret
    486