xref: /netbsd/sys/arch/i386/stand/lib/crt/dos/start_dos.S (revision bf9ec67e)
1/*	$NetBSD: start_dos.S,v 1.6 1999/08/23 08:24:38 kleink Exp $	*/
2
3/*
4 * startup for DOS .COM programs
5 * with input from:
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
10 */
11
12/*
13 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
14 *
15 * Mach Operating System
16 * Copyright (c) 1992, 1991 Carnegie Mellon University
17 * All Rights Reserved.
18 *
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.
24 *
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.
28 *
29 * Carnegie Mellon requests users of this software to return to
30 *
31 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
32 *  School of Computer Science
33 *  Carnegie Mellon University
34 *  Pittsburgh PA 15213-3890
35 *
36 * any improvements or extensions that they make and grant Carnegie Mellon
37 * the rights to redistribute these changes.
38 */
39
40/*
41  Copyright 1988, 1989, 1990, 1991, 1992
42   by Intel Corporation, Santa Clara, California.
43
44                All Rights Reserved
45
46Permission to use, copy, modify, and distribute this software and
47its documentation for any purpose and without fee is hereby
48granted, provided that the above copyright notice appears in all
49copies and that both the copyright notice and this permission notice
50appear in supporting documentation, and that the name of Intel
51not be used in advertising or publicity pertaining to distribution
52of the software without specific, written prior permission.
53
54INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
55INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
56IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
57CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
58LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
59NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
60WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
61*/
62
63#include <machine/asm.h>
64#define	addr32	.byte 0x67
65#define	data32	.byte 0x66
66
67	.data
68	.globl _C_LABEL(ourseg)
69_C_LABEL(ourseg):
70	.long	0
71
72/**************************************************************************
73GLOBAL DESCRIPTOR TABLE
74**************************************************************************/
75#ifdef __ELF__
76	.align	16
77#else
78	.align	4
79#endif
80gdt:
81	.word	0, 0
82	.byte	0, 0x00, 0x00, 0
83
84#ifdef SUPPORT_LINUX	/* additional dummy */
85	.word	0, 0
86	.byte	0, 0x00, 0x00, 0
87#endif
88
89	/* kernel code segment */
90	.globl flatcodeseg
91flatcodeseg = . - gdt
92	.word	0xffff, 0
93	.byte	0, 0x9f, 0xcf, 0
94
95	/* kernel data segment */
96	.globl flatdataseg
97flatdataseg = . - gdt
98	.word	0xffff, 0
99	.byte	0, 0x93, 0xcf, 0
100
101	/* boot code segment, will be patched */
102bootcodeseg = . - gdt
103	.word	0xffff, 0
104	.byte	0, 0x9e, 0x40, 0
105
106	/* boot data segment, will be patched */
107bootdataseg = . - gdt
108#ifdef HEAP_BELOW_64K
109	.word	0xffff, 0
110	.byte	0, 0x92, 0x00, 0
111#else
112	.word	0xffff, 0
113	.byte	0, 0x92, 0x0f, 0
114#endif
115
116	/* 16 bit real mode, will be patched */
117bootrealseg = . - gdt
118	.word	0xffff, 0
119	.byte	0, 0x9e, 0x00, 0
120gdtlen = . - gdt
121
122#ifdef __ELF__
123	.align	16
124#else
125	.align	4
126#endif
127gdtarg:
128	.word	gdtlen-1		/* limit */
129	.long	0			/* addr, will be inserted */
130
131	.text
132ENTRY(start)
133	data32
134	xorl	%eax, %eax
135	movl	%cs, %ax
136	movl	%ax, %ds
137	movl	%ax, %es
138	addr32
139	data32
140	movl	%eax, _C_LABEL(ourseg)
141	data32
142	shll	$4, %eax
143
144	/* fix up GDT entries for bootstrap */
145#define FIXUP(gdt_index) \
146	addr32; \
147	movl	%eax, gdt+gdt_index+2;	/* actually movw %ax */ \
148	addr32; \
149	movb	%bl, gdt+gdt_index+4
150
151	data32
152	shldl	$16, %eax, %ebx
153	FIXUP(bootcodeseg)
154	FIXUP(bootrealseg)
155	FIXUP(bootdataseg)
156
157	/* fix up GDT pointer */
158	data32
159	addl	$gdt, %eax
160	addr32
161	data32
162	movl	%eax, gdtarg+2
163
164	/* change to protected mode */
165	data32
166	call	_C_LABEL(real_to_prot)
167
168	/* clear the bss */
169	movl	$_C_LABEL(edata), %edi
170	movl	$_C_LABEL(end), %ecx
171	subl	%edi, %ecx
172	subb	%al, %al
173	rep
174	stosb
175
176	call	_C_LABEL(doscommain)
177ENTRY(exit)
178	call	_C_LABEL(prot_to_real)
179	sti
180	movb	$0x4c,%ah /* return */
181	int	$0x21
182
183CR0_PE		=	0x1
184
185/*
186 * real_to_prot()
187 * 	transfer from real mode to protected mode.
188 */
189ENTRY(real_to_prot)
190	# guarantee that interrupt is disabled when in prot mode
191	cli
192
193	# load the gdtr
194	addr32
195	data32
196	lgdt	gdtarg
197
198	# set the PE bit of CR0
199	movl	%cr0, %eax
200
201	data32
202	orl	$CR0_PE, %eax
203	movl	%eax, %cr0
204
205	# make intrasegment jump to flush the processor pipeline and
206	# reload CS register
207	data32
208	ljmp	$bootcodeseg, $xprot
209
210xprot:
211	# we are in USE32 mode now
212	# set up the protected mode segment registers : DS, SS, ES
213	movl	$bootdataseg, %eax
214	movl	%ax, %ds
215	movl	%ax, %ss
216	movl	%ax, %es
217
218	ret
219
220/*
221 * prot_to_real()
222 * 	transfer from protected mode to real mode
223 */
224ENTRY(prot_to_real)
225	# set up a dummy stack frame for the second seg change.
226	# Adjust the intersegment jump instruction following
227	# the clearing of protected mode bit.
228	# This is self-modifying code, but we need a writable
229	# code segment, and an intersegment return does not give us that.
230
231	movl	_C_LABEL(ourseg), %eax
232	movw	%ax, xreal-2
233
234	# Change to use16 mode.
235	ljmp	$bootrealseg, $x16
236
237x16:
238	# clear the PE bit of CR0
239	movl	%cr0, %eax
240	data32
241	andl 	$~CR0_PE, %eax
242	movl	%eax, %cr0
243	# Here we have an 16 bits intersegment jump.
244	.byte 0xea
245	.word xreal
246	.word 0
247
248xreal:
249	# we are in real mode now
250	# set up the real mode segment registers : DS, SS, ES
251	movl	%cs, %ax
252	movl	%ax, %ds
253	movl	%ax, %ss
254	movl	%ax, %es
255
256	sti
257	data32
258	ret
259
260/**************************************************************************
261___MAIN - Dummy to keep GCC happy
262**************************************************************************/
263ENTRY(__main)
264	ret
265
266/*
267 * pbzero(dst, cnt)
268 *	where dst is a physical address and cnt is the length
269 */
270ENTRY(pbzero)
271	pushl	%ebp
272	movl	%esp, %ebp
273	pushl	%es
274	pushl	%edi
275
276	cld
277
278	# set %es to point at the flat segment
279	movl	$flatdataseg, %eax
280	movl	%ax, %es
281
282	movl	8(%ebp), %edi		# destination
283	movl	12(%ebp), %ecx		# count
284	xorl	%eax, %eax		# value
285
286	rep
287	stosb
288
289	popl	%edi
290	popl	%es
291	popl	%ebp
292	ret
293
294/*
295 * vpbcopy(src, dst, cnt)
296 *	where src is a virtual address and dst is a physical address
297 */
298ENTRY(vpbcopy)
299	pushl	%ebp
300	movl	%esp, %ebp
301	pushl	%es
302	pushl	%esi
303	pushl	%edi
304
305	cld
306
307	# set %es to point at the flat segment
308	movl	$flatdataseg, %eax
309	movl	%ax, %es
310
311	movl	8(%ebp), %esi		# source
312	movl	12(%ebp), %edi		# destination
313	movl	16(%ebp), %ecx		# count
314
315	rep
316	movsb
317
318	popl	%edi
319	popl	%esi
320	popl	%es
321	popl	%ebp
322	ret
323
324/*
325 * pvbcopy(src, dst, cnt)
326 *	where src is a physical address and dst is a virtual address
327 */
328ENTRY(pvbcopy)
329	pushl	%ebp
330	movl	%esp, %ebp
331	pushl	%ds
332	pushl	%esi
333	pushl	%edi
334
335	cld
336
337	# set %ds to point at the flat segment
338	movl	$flatdataseg, %eax
339	movl	%ax, %ds
340
341	movl	8(%ebp), %esi		# source
342	movl	12(%ebp), %edi		# destination
343	movl	16(%ebp), %ecx		# count
344
345	rep
346	movsb
347
348	popl	%edi
349	popl	%esi
350	popl	%ds
351	popl	%ebp
352	ret
353
354ENTRY(vtophys)
355	movl _C_LABEL(ourseg), %eax
356	shll	$4, %eax
357	addl 4(%esp), %eax
358	ret
359
360#ifdef XMS
361
362/* pointer to XMS driver, 0 if no XMS used */
363
364	.data
365_C_LABEL(xmsdrv):
366	.long	0
367
368	.text
369ENTRY(checkxms)
370	pushl %ebp
371	movl  %esp, %ebp
372	pushl	%ebx
373	pushl	%edx
374	pushl	%es
375	pushl	%esi
376	pushl	%edi
377
378	call	_C_LABEL(prot_to_real)	# enter real mode
379
380	.byte	0xb8	/* movw $0x4300,ax */
381	.word	0x4300
382	int	$0x2f	/* check if XMS installed */
383	cmpb	$0x80, %al
384	jnz	noxms
385
386	.byte	0xb8	/* movw $0x4310,ax */
387	.word	0x4310
388	int	$0x2f	/* get driver address */
389
390	.byte	0x89,0x1e	/* save es:bx to _xmsdrv */
391	.word	_C_LABEL(xmsdrv)
392	.byte	0x8c,0x06
393	.word	_C_LABEL(xmsdrv)+2
394
395	movb	$0x08, %ah	/* XMS: query free extended memory */
396#if 0
397	movb	$0x00, %bl
398#endif
399	.byte	0xff, 0x1e
400	.word	_C_LABEL(xmsdrv)  /* result in dx */
401	jmp	xdone
402
403noxms:		/* no XMS manager found */
404	movl	$0, %edx /* comes out as movw ! */
405
406xdone:
407	data32
408	call	_C_LABEL(real_to_prot) # back to protected mode
409
410	xorl	%eax, %eax
411	movw	%dx, %ax
412
413	popl	%edi
414	popl	%esi
415	popl	%es
416	popl	%edx
417	popl	%ebx
418	popl	%ebp
419	ret
420
421/*
422	Allocate a block of XMS memory with the requested size
423		void * xmsalloc(long int kBytes);
424
425	Depends on _xmsdrv being set by getextmem() before first call
426	to this function.
427
428	Return value: a physical address.
429*/
430ENTRY(xmsalloc)
431	pushl %ebp
432	movl  %esp, %ebp
433	pushl	%ebx
434	pushl	%edx
435	pushl	%esi
436	pushl	%edi
437
438	movl	0x8(%ebp), %edx # Kbytes needed
439
440	call	_C_LABEL(prot_to_real)	# enter real mode
441
442	movb	$0x09, %ah	# XMS allocate block
443	.byte 0xff,0x1e
444	.word _C_LABEL(xmsdrv)	# result: handle in %dx
445	movb	$0x0c, %ah	# XMS lock block
446	.byte 0xff,0x1e
447	.word _C_LABEL(xmsdrv)	# result: 32 bit physical address in DX:BX
448
449	data32
450	call	_C_LABEL(real_to_prot) # back to protected mode
451
452	movl	%edx, %eax
453	shl	$16, %eax
454	movw	%bx, %ax	# result in %eax
455
456	popl	%edi
457	popl	%esi
458	popl	%edx
459	popl	%ebx
460	popl	%ebp
461	ret
462
463/*
464 * ppbcopy(src, dst, cnt)
465 *	where src and dst are physical addresses
466 */
467ENTRY(ppbcopy)
468	pushl	%ebp
469	movl	%esp, %ebp
470	pushl	%es
471	pushl	%esi
472	pushl	%edi
473
474	cld
475
476	# set %es to point at the flat segment
477	movl	$flatdataseg, %eax
478	movl	%ax, %es
479
480	movl	8(%ebp), %esi		# source
481	movl	12(%ebp), %edi		# destination
482	movl	16(%ebp), %ecx		# count
483
484	es
485	rep
486	movsb
487
488	popl	%edi
489	popl	%esi
490	popl	%es
491	popl	%ebp
492	ret
493
494#endif
495