1*58a2b000SEvgeniy Ivanov/* $NetBSD: start_dos.S,v 1.10 2010/12/20 01:12:44 jakllsch Exp $ */ 2*58a2b000SEvgeniy Ivanov 3*58a2b000SEvgeniy Ivanov/* 4*58a2b000SEvgeniy Ivanov * startup for DOS .COM programs 5*58a2b000SEvgeniy Ivanov * with input from: 6*58a2b000SEvgeniy Ivanov * netbsd:sys/arch/i386/boot/start.S 7*58a2b000SEvgeniy Ivanov * Tor Egge's patches for NetBSD boot (pr port-i386/1002) 8*58a2b000SEvgeniy Ivanov * freebsd:sys/i386/boot/netboot/start2.S 9*58a2b000SEvgeniy Ivanov * XMS support by Martin Husemann 10*58a2b000SEvgeniy Ivanov */ 11*58a2b000SEvgeniy Ivanov 12*58a2b000SEvgeniy Ivanov/* 13*58a2b000SEvgeniy Ivanov * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 14*58a2b000SEvgeniy Ivanov * 15*58a2b000SEvgeniy Ivanov * Mach Operating System 16*58a2b000SEvgeniy Ivanov * Copyright (c) 1992, 1991 Carnegie Mellon University 17*58a2b000SEvgeniy Ivanov * All Rights Reserved. 18*58a2b000SEvgeniy Ivanov * 19*58a2b000SEvgeniy Ivanov * Permission to use, copy, modify and distribute this software and its 20*58a2b000SEvgeniy Ivanov * documentation is hereby granted, provided that both the copyright 21*58a2b000SEvgeniy Ivanov * notice and this permission notice appear in all copies of the 22*58a2b000SEvgeniy Ivanov * software, derivative works or modified versions, and any portions 23*58a2b000SEvgeniy Ivanov * thereof, and that both notices appear in supporting documentation. 24*58a2b000SEvgeniy Ivanov * 25*58a2b000SEvgeniy Ivanov * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 26*58a2b000SEvgeniy Ivanov * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 27*58a2b000SEvgeniy Ivanov * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 28*58a2b000SEvgeniy Ivanov * 29*58a2b000SEvgeniy Ivanov * Carnegie Mellon requests users of this software to return to 30*58a2b000SEvgeniy Ivanov * 31*58a2b000SEvgeniy Ivanov * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 32*58a2b000SEvgeniy Ivanov * School of Computer Science 33*58a2b000SEvgeniy Ivanov * Carnegie Mellon University 34*58a2b000SEvgeniy Ivanov * Pittsburgh PA 15213-3890 35*58a2b000SEvgeniy Ivanov * 36*58a2b000SEvgeniy Ivanov * any improvements or extensions that they make and grant Carnegie Mellon 37*58a2b000SEvgeniy Ivanov * the rights to redistribute these changes. 38*58a2b000SEvgeniy Ivanov */ 39*58a2b000SEvgeniy Ivanov 40*58a2b000SEvgeniy Ivanov/* 41*58a2b000SEvgeniy Ivanov Copyright 1988, 1989, 1990, 1991, 1992 42*58a2b000SEvgeniy Ivanov by Intel Corporation, Santa Clara, California. 43*58a2b000SEvgeniy Ivanov 44*58a2b000SEvgeniy Ivanov All Rights Reserved 45*58a2b000SEvgeniy Ivanov 46*58a2b000SEvgeniy IvanovPermission to use, copy, modify, and distribute this software and 47*58a2b000SEvgeniy Ivanovits documentation for any purpose and without fee is hereby 48*58a2b000SEvgeniy Ivanovgranted, provided that the above copyright notice appears in all 49*58a2b000SEvgeniy Ivanovcopies and that both the copyright notice and this permission notice 50*58a2b000SEvgeniy Ivanovappear in supporting documentation, and that the name of Intel 51*58a2b000SEvgeniy Ivanovnot be used in advertising or publicity pertaining to distribution 52*58a2b000SEvgeniy Ivanovof the software without specific, written prior permission. 53*58a2b000SEvgeniy Ivanov 54*58a2b000SEvgeniy IvanovINTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 55*58a2b000SEvgeniy IvanovINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, 56*58a2b000SEvgeniy IvanovIN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 57*58a2b000SEvgeniy IvanovCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 58*58a2b000SEvgeniy IvanovLOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 59*58a2b000SEvgeniy IvanovNEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 60*58a2b000SEvgeniy IvanovWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 61*58a2b000SEvgeniy Ivanov*/ 62*58a2b000SEvgeniy Ivanov 63*58a2b000SEvgeniy Ivanov#include <machine/asm.h> 64*58a2b000SEvgeniy Ivanov 65*58a2b000SEvgeniy Ivanov 66*58a2b000SEvgeniy IvanovCR0_PE = 0x1 67*58a2b000SEvgeniy Ivanov 68*58a2b000SEvgeniy Ivanov .data 69*58a2b000SEvgeniy Ivanov .globl _C_LABEL(ourseg) 70*58a2b000SEvgeniy Ivanov_C_LABEL(ourseg): 71*58a2b000SEvgeniy Ivanov .long 0 72*58a2b000SEvgeniy Ivanov 73*58a2b000SEvgeniy Ivanov/************************************************************************** 74*58a2b000SEvgeniy IvanovGLOBAL DESCRIPTOR TABLE 75*58a2b000SEvgeniy Ivanov**************************************************************************/ 76*58a2b000SEvgeniy Ivanov#ifdef __ELF__ 77*58a2b000SEvgeniy Ivanov .align 16 78*58a2b000SEvgeniy Ivanov#else 79*58a2b000SEvgeniy Ivanov .align 4 80*58a2b000SEvgeniy Ivanov#endif 81*58a2b000SEvgeniy Ivanovgdt: 82*58a2b000SEvgeniy Ivanov .word 0, 0 83*58a2b000SEvgeniy Ivanov .byte 0, 0x00, 0x00, 0 84*58a2b000SEvgeniy Ivanov 85*58a2b000SEvgeniy Ivanov#ifdef SUPPORT_LINUX /* additional dummy */ 86*58a2b000SEvgeniy Ivanov .word 0, 0 87*58a2b000SEvgeniy Ivanov .byte 0, 0x00, 0x00, 0 88*58a2b000SEvgeniy Ivanov#endif 89*58a2b000SEvgeniy Ivanov 90*58a2b000SEvgeniy Ivanov /* kernel code segment */ 91*58a2b000SEvgeniy Ivanov .globl flatcodeseg 92*58a2b000SEvgeniy Ivanovflatcodeseg = . - gdt 93*58a2b000SEvgeniy Ivanov .word 0xffff, 0 94*58a2b000SEvgeniy Ivanov .byte 0, 0x9f, 0xcf, 0 95*58a2b000SEvgeniy Ivanov 96*58a2b000SEvgeniy Ivanov /* kernel data segment */ 97*58a2b000SEvgeniy Ivanov .globl flatdataseg 98*58a2b000SEvgeniy Ivanovflatdataseg = . - gdt 99*58a2b000SEvgeniy Ivanov .word 0xffff, 0 100*58a2b000SEvgeniy Ivanov .byte 0, 0x93, 0xcf, 0 101*58a2b000SEvgeniy Ivanov 102*58a2b000SEvgeniy Ivanov /* boot code segment, base will be patched */ 103*58a2b000SEvgeniy Ivanovbootcodeseg = . - gdt 104*58a2b000SEvgeniy Ivanov .word 0xffff, 0 105*58a2b000SEvgeniy Ivanov .byte 0, 0x9e, 0x40, 0 106*58a2b000SEvgeniy Ivanov 107*58a2b000SEvgeniy Ivanov /* boot data segment, base will be patched */ 108*58a2b000SEvgeniy Ivanovbootdataseg = . - gdt 109*58a2b000SEvgeniy Ivanov#ifdef HEAP_BELOW_64K 110*58a2b000SEvgeniy Ivanov .word 0xffff, 0 111*58a2b000SEvgeniy Ivanov .byte 0, 0x92, 0x00, 0 112*58a2b000SEvgeniy Ivanov#else 113*58a2b000SEvgeniy Ivanov .word 0xffff, 0 114*58a2b000SEvgeniy Ivanov .byte 0, 0x92, 0x4f, 0 115*58a2b000SEvgeniy Ivanov#endif 116*58a2b000SEvgeniy Ivanov 117*58a2b000SEvgeniy Ivanov /* 16 bit real mode, base will be patched */ 118*58a2b000SEvgeniy Ivanovbootrealseg = . - gdt 119*58a2b000SEvgeniy Ivanov .word 0xffff, 0 120*58a2b000SEvgeniy Ivanov .byte 0, 0x9e, 0x00, 0 121*58a2b000SEvgeniy Ivanov 122*58a2b000SEvgeniy Ivanov /* limits (etc) for data segment in real mode */ 123*58a2b000SEvgeniy Ivanovbootrealdata = . - gdt 124*58a2b000SEvgeniy Ivanov .word 0xffff, 0 125*58a2b000SEvgeniy Ivanov .byte 0, 0x92, 0x00, 0 126*58a2b000SEvgeniy Ivanovgdtlen = . - gdt 127*58a2b000SEvgeniy Ivanov 128*58a2b000SEvgeniy Ivanov#ifdef __ELF__ 129*58a2b000SEvgeniy Ivanov .align 16 130*58a2b000SEvgeniy Ivanov#else 131*58a2b000SEvgeniy Ivanov .align 4 132*58a2b000SEvgeniy Ivanov#endif 133*58a2b000SEvgeniy Ivanovgdtarg: 134*58a2b000SEvgeniy Ivanov .word gdtlen-1 /* limit */ 135*58a2b000SEvgeniy Ivanov .long 0 /* addr, will be inserted */ 136*58a2b000SEvgeniy Ivanov 137*58a2b000SEvgeniy Ivanov .text 138*58a2b000SEvgeniy IvanovENTRY(start) 139*58a2b000SEvgeniy Ivanov .code16 140*58a2b000SEvgeniy Ivanov 141*58a2b000SEvgeniy Ivanov # Check we are in real mode 142*58a2b000SEvgeniy Ivanov movl %cr0, %eax 143*58a2b000SEvgeniy Ivanov testl $CR0_PE, %eax 144*58a2b000SEvgeniy Ivanov jz 2f 145*58a2b000SEvgeniy Ivanov mov $1f, %si 146*58a2b000SEvgeniy Ivanov call message 147*58a2b000SEvgeniy Ivanov ret 148*58a2b000SEvgeniy Ivanov1: .asciz "must be in real mode\r\n" 149*58a2b000SEvgeniy Ivanov2: 150*58a2b000SEvgeniy Ivanov 151*58a2b000SEvgeniy Ivanov xorl %eax, %eax 152*58a2b000SEvgeniy Ivanov mov %cs, %ax 153*58a2b000SEvgeniy Ivanov mov %ax, %ds 154*58a2b000SEvgeniy Ivanov mov %ax, %es 155*58a2b000SEvgeniy Ivanov movl %eax, _C_LABEL(ourseg) 156*58a2b000SEvgeniy Ivanov#ifdef STACK_START 157*58a2b000SEvgeniy Ivanov add $STACK_START / 16, %ax 158*58a2b000SEvgeniy Ivanov mov %ax, %ss 159*58a2b000SEvgeniy Ivanov mov $0xfffc, %sp 160*58a2b000SEvgeniy Ivanov#endif 161*58a2b000SEvgeniy Ivanov 162*58a2b000SEvgeniy Ivanov /* fix up GDT entries for bootstrap */ 163*58a2b000SEvgeniy Ivanov#define FIXUP(gdt_index) \ 164*58a2b000SEvgeniy Ivanov movw %ax, gdt+gdt_index+2; \ 165*58a2b000SEvgeniy Ivanov movb %bl, gdt+gdt_index+4 166*58a2b000SEvgeniy Ivanov 167*58a2b000SEvgeniy Ivanov mov %cs, %ax 168*58a2b000SEvgeniy Ivanov shll $4, %eax 169*58a2b000SEvgeniy Ivanov shldl $16, %eax, %ebx 170*58a2b000SEvgeniy Ivanov FIXUP(bootcodeseg) 171*58a2b000SEvgeniy Ivanov FIXUP(bootrealseg) 172*58a2b000SEvgeniy Ivanov FIXUP(bootdataseg) 173*58a2b000SEvgeniy Ivanov 174*58a2b000SEvgeniy Ivanov /* fix up GDT pointer */ 175*58a2b000SEvgeniy Ivanov addl $gdt, %eax 176*58a2b000SEvgeniy Ivanov movl %eax, gdtarg+2 177*58a2b000SEvgeniy Ivanov 178*58a2b000SEvgeniy Ivanov /* change to protected mode */ 179*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 180*58a2b000SEvgeniy Ivanov .code32 181*58a2b000SEvgeniy Ivanov 182*58a2b000SEvgeniy Ivanov /* clear the bss */ 183*58a2b000SEvgeniy Ivanov movl $_C_LABEL(edata), %edi 184*58a2b000SEvgeniy Ivanov movl $_C_LABEL(end), %ecx 185*58a2b000SEvgeniy Ivanov subl %edi, %ecx 186*58a2b000SEvgeniy Ivanov xorb %al, %al 187*58a2b000SEvgeniy Ivanov rep 188*58a2b000SEvgeniy Ivanov stosb 189*58a2b000SEvgeniy Ivanov 190*58a2b000SEvgeniy Ivanov call _C_LABEL(doscommain) 191*58a2b000SEvgeniy IvanovENTRY(_rtt) 192*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 193*58a2b000SEvgeniy Ivanov .code16 194*58a2b000SEvgeniy IvanovENTRY(exit16) 195*58a2b000SEvgeniy Ivanov sti 196*58a2b000SEvgeniy Ivanov movb $0x4c, %ah /* return */ 197*58a2b000SEvgeniy Ivanov int $0x21 198*58a2b000SEvgeniy Ivanov 199*58a2b000SEvgeniy Ivanov/* 200*58a2b000SEvgeniy Ivanov * real_to_prot() 201*58a2b000SEvgeniy Ivanov * transfer from real mode to protected mode. 202*58a2b000SEvgeniy Ivanov */ 203*58a2b000SEvgeniy IvanovENTRY(real_to_prot) 204*58a2b000SEvgeniy Ivanov .code16 205*58a2b000SEvgeniy Ivanov pushl %eax 206*58a2b000SEvgeniy Ivanov # guarantee that interrupt is disabled when in prot mode 207*58a2b000SEvgeniy Ivanov cli 208*58a2b000SEvgeniy Ivanov 209*58a2b000SEvgeniy Ivanov # load the gdtr 210*58a2b000SEvgeniy Ivanov lgdtl %cs:gdtarg 211*58a2b000SEvgeniy Ivanov 212*58a2b000SEvgeniy Ivanov # set the PE bit of CR0 213*58a2b000SEvgeniy Ivanov movl %cr0, %eax 214*58a2b000SEvgeniy Ivanov orl $CR0_PE, %eax 215*58a2b000SEvgeniy Ivanov movl %eax, %cr0 216*58a2b000SEvgeniy Ivanov 217*58a2b000SEvgeniy Ivanov # make intrasegment jump to flush the processor pipeline and 218*58a2b000SEvgeniy Ivanov # reload CS register 219*58a2b000SEvgeniy Ivanov ljmp $bootcodeseg, $xprot 220*58a2b000SEvgeniy Ivanov 221*58a2b000SEvgeniy Ivanovxprot: 222*58a2b000SEvgeniy Ivanov .code32 223*58a2b000SEvgeniy Ivanov # we are in USE32 mode now 224*58a2b000SEvgeniy Ivanov # set up the protected mode segment registers : DS, SS, ES 225*58a2b000SEvgeniy Ivanov movl $bootdataseg, %eax 226*58a2b000SEvgeniy Ivanov mov %ax, %ds 227*58a2b000SEvgeniy Ivanov mov %ax, %es 228*58a2b000SEvgeniy Ivanov mov %ax, %ss 229*58a2b000SEvgeniy Ivanov#ifdef STACK_START 230*58a2b000SEvgeniy Ivanov addl $STACK_START, %esp 231*58a2b000SEvgeniy Ivanov#endif 232*58a2b000SEvgeniy Ivanov 233*58a2b000SEvgeniy Ivanov popl %eax 234*58a2b000SEvgeniy Ivanov ret 235*58a2b000SEvgeniy Ivanov 236*58a2b000SEvgeniy Ivanov/* 237*58a2b000SEvgeniy Ivanov * prot_to_real() 238*58a2b000SEvgeniy Ivanov * transfer from protected mode to real mode 239*58a2b000SEvgeniy Ivanov */ 240*58a2b000SEvgeniy IvanovENTRY(prot_to_real) 241*58a2b000SEvgeniy Ivanov .code32 242*58a2b000SEvgeniy Ivanov pushl %eax 243*58a2b000SEvgeniy Ivanov # set up a dummy stack frame for the second seg change. 244*58a2b000SEvgeniy Ivanov # Adjust the intersegment jump instruction following 245*58a2b000SEvgeniy Ivanov # the clearing of protected mode bit. 246*58a2b000SEvgeniy Ivanov # This is self-modifying code, but we need a writable 247*58a2b000SEvgeniy Ivanov # code segment, and an intersegment return does not give us that. 248*58a2b000SEvgeniy Ivanov 249*58a2b000SEvgeniy Ivanov movl _C_LABEL(ourseg), %eax 250*58a2b000SEvgeniy Ivanov movw %ax, xreal-2 251*58a2b000SEvgeniy Ivanov 252*58a2b000SEvgeniy Ivanov /* 253*58a2b000SEvgeniy Ivanov * Load the segment registers while still in protected mode. 254*58a2b000SEvgeniy Ivanov * Otherwise the control bits don't get changed. 255*58a2b000SEvgeniy Ivanov * The correct values are loaded later. 256*58a2b000SEvgeniy Ivanov */ 257*58a2b000SEvgeniy Ivanov movw $bootrealdata, %ax 258*58a2b000SEvgeniy Ivanov movw %ax, %ds 259*58a2b000SEvgeniy Ivanov movw %ax, %es 260*58a2b000SEvgeniy Ivanov movw %ax, %ss 261*58a2b000SEvgeniy Ivanov 262*58a2b000SEvgeniy Ivanov # Change to use16 mode. 263*58a2b000SEvgeniy Ivanov ljmp $bootrealseg, $x16 264*58a2b000SEvgeniy Ivanov 265*58a2b000SEvgeniy Ivanovx16: 266*58a2b000SEvgeniy Ivanov .code16 267*58a2b000SEvgeniy Ivanov # clear the PE bit of CR0 268*58a2b000SEvgeniy Ivanov movl %cr0, %eax 269*58a2b000SEvgeniy Ivanov andl $~CR0_PE, %eax 270*58a2b000SEvgeniy Ivanov movl %eax, %cr0 271*58a2b000SEvgeniy Ivanov 272*58a2b000SEvgeniy Ivanov # Here we have an 16 bits intersegment jump. 273*58a2b000SEvgeniy Ivanov ljmp $0, $xreal /* segment patched above */ 274*58a2b000SEvgeniy Ivanov 275*58a2b000SEvgeniy Ivanovxreal: 276*58a2b000SEvgeniy Ivanov # we are in real mode now 277*58a2b000SEvgeniy Ivanov # set up the real mode segment registers : DS, SS, ES 278*58a2b000SEvgeniy Ivanov mov %cs, %ax 279*58a2b000SEvgeniy Ivanov mov %ax, %ds 280*58a2b000SEvgeniy Ivanov mov %ax, %es 281*58a2b000SEvgeniy Ivanov#ifdef STACK_START 282*58a2b000SEvgeniy Ivanov add $STACK_START / 16, %ax 283*58a2b000SEvgeniy Ivanov mov %ax, %ss 284*58a2b000SEvgeniy Ivanov subl $STACK_START, %esp 285*58a2b000SEvgeniy Ivanov#else 286*58a2b000SEvgeniy Ivanov mov %ax, %ss 287*58a2b000SEvgeniy Ivanov#endif 288*58a2b000SEvgeniy Ivanov push %bp 289*58a2b000SEvgeniy Ivanov movw %sp, %bp 290*58a2b000SEvgeniy Ivanov /* check we are returning to an address below 64k */ 291*58a2b000SEvgeniy Ivanov movw 2/*bp*/ + 4/*eax*/ + 2(%bp), %ax /* high bits ret addr */ 292*58a2b000SEvgeniy Ivanov test %ax, %ax 293*58a2b000SEvgeniy Ivanov jne 1f 294*58a2b000SEvgeniy Ivanov pop %bp 295*58a2b000SEvgeniy Ivanov 296*58a2b000SEvgeniy Ivanov sti 297*58a2b000SEvgeniy Ivanov popl %eax 298*58a2b000SEvgeniy Ivanov retl 299*58a2b000SEvgeniy Ivanov 300*58a2b000SEvgeniy Ivanov1: movw $2f, %si 301*58a2b000SEvgeniy Ivanov call message 302*58a2b000SEvgeniy Ivanov movl 2/*bp*/ + 4/*eax*/(%bp), %eax /* return address */ 303*58a2b000SEvgeniy Ivanov call dump_eax 304*58a2b000SEvgeniy Ivanov jmp exit16 305*58a2b000SEvgeniy Ivanov2: .asciz "prot_to_real can't return to " 306*58a2b000SEvgeniy Ivanov 307*58a2b000SEvgeniy Ivanov 308*58a2b000SEvgeniy Ivanov/************************************************************************** 309*58a2b000SEvgeniy Ivanov___MAIN - Dummy to keep GCC happy 310*58a2b000SEvgeniy Ivanov**************************************************************************/ 311*58a2b000SEvgeniy IvanovENTRY(__main) 312*58a2b000SEvgeniy Ivanov ret 313*58a2b000SEvgeniy Ivanov 314*58a2b000SEvgeniy Ivanov/* 315*58a2b000SEvgeniy Ivanov * pbzero(dst, cnt) 316*58a2b000SEvgeniy Ivanov * where dst is a physical address and cnt is the length 317*58a2b000SEvgeniy Ivanov */ 318*58a2b000SEvgeniy IvanovENTRY(pbzero) 319*58a2b000SEvgeniy Ivanov .code32 320*58a2b000SEvgeniy Ivanov pushl %ebp 321*58a2b000SEvgeniy Ivanov movl %esp, %ebp 322*58a2b000SEvgeniy Ivanov pushl %es 323*58a2b000SEvgeniy Ivanov pushl %edi 324*58a2b000SEvgeniy Ivanov 325*58a2b000SEvgeniy Ivanov cld 326*58a2b000SEvgeniy Ivanov 327*58a2b000SEvgeniy Ivanov # set %es to point at the flat segment 328*58a2b000SEvgeniy Ivanov movl $flatdataseg, %eax 329*58a2b000SEvgeniy Ivanov mov %ax, %es 330*58a2b000SEvgeniy Ivanov 331*58a2b000SEvgeniy Ivanov movl 8(%ebp), %edi # destination 332*58a2b000SEvgeniy Ivanov movl 12(%ebp), %ecx # count 333*58a2b000SEvgeniy Ivanov xorl %eax, %eax # value 334*58a2b000SEvgeniy Ivanov 335*58a2b000SEvgeniy Ivanov rep 336*58a2b000SEvgeniy Ivanov stosb 337*58a2b000SEvgeniy Ivanov 338*58a2b000SEvgeniy Ivanov popl %edi 339*58a2b000SEvgeniy Ivanov popl %es 340*58a2b000SEvgeniy Ivanov popl %ebp 341*58a2b000SEvgeniy Ivanov ret 342*58a2b000SEvgeniy Ivanov 343*58a2b000SEvgeniy Ivanov/* 344*58a2b000SEvgeniy Ivanov * vpbcopy(src, dst, cnt) 345*58a2b000SEvgeniy Ivanov * where src is a virtual address and dst is a physical address 346*58a2b000SEvgeniy Ivanov */ 347*58a2b000SEvgeniy IvanovENTRY(vpbcopy) 348*58a2b000SEvgeniy Ivanov .code32 349*58a2b000SEvgeniy Ivanov pushl %ebp 350*58a2b000SEvgeniy Ivanov movl %esp, %ebp 351*58a2b000SEvgeniy Ivanov pushl %es 352*58a2b000SEvgeniy Ivanov pushl %esi 353*58a2b000SEvgeniy Ivanov pushl %edi 354*58a2b000SEvgeniy Ivanov 355*58a2b000SEvgeniy Ivanov cld 356*58a2b000SEvgeniy Ivanov 357*58a2b000SEvgeniy Ivanov # set %es to point at the flat segment 358*58a2b000SEvgeniy Ivanov movl $flatdataseg, %eax 359*58a2b000SEvgeniy Ivanov mov %ax, %es 360*58a2b000SEvgeniy Ivanov 361*58a2b000SEvgeniy Ivanov movl 8(%ebp), %esi # source 362*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edi # destination 363*58a2b000SEvgeniy Ivanov movl 16(%ebp), %ecx # count 364*58a2b000SEvgeniy Ivanov 365*58a2b000SEvgeniy Ivanov rep 366*58a2b000SEvgeniy Ivanov movsb 367*58a2b000SEvgeniy Ivanov 368*58a2b000SEvgeniy Ivanov popl %edi 369*58a2b000SEvgeniy Ivanov popl %esi 370*58a2b000SEvgeniy Ivanov popl %es 371*58a2b000SEvgeniy Ivanov popl %ebp 372*58a2b000SEvgeniy Ivanov ret 373*58a2b000SEvgeniy Ivanov 374*58a2b000SEvgeniy Ivanov/* 375*58a2b000SEvgeniy Ivanov * pvbcopy(src, dst, cnt) 376*58a2b000SEvgeniy Ivanov * where src is a physical address and dst is a virtual address 377*58a2b000SEvgeniy Ivanov */ 378*58a2b000SEvgeniy IvanovENTRY(pvbcopy) 379*58a2b000SEvgeniy Ivanov .code32 380*58a2b000SEvgeniy Ivanov pushl %ebp 381*58a2b000SEvgeniy Ivanov movl %esp, %ebp 382*58a2b000SEvgeniy Ivanov pushl %ds 383*58a2b000SEvgeniy Ivanov pushl %esi 384*58a2b000SEvgeniy Ivanov pushl %edi 385*58a2b000SEvgeniy Ivanov 386*58a2b000SEvgeniy Ivanov cld 387*58a2b000SEvgeniy Ivanov 388*58a2b000SEvgeniy Ivanov # set %ds to point at the flat segment 389*58a2b000SEvgeniy Ivanov movl $flatdataseg, %eax 390*58a2b000SEvgeniy Ivanov mov %ax, %ds 391*58a2b000SEvgeniy Ivanov 392*58a2b000SEvgeniy Ivanov movl 8(%ebp), %esi # source 393*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edi # destination 394*58a2b000SEvgeniy Ivanov movl 16(%ebp), %ecx # count 395*58a2b000SEvgeniy Ivanov 396*58a2b000SEvgeniy Ivanov rep 397*58a2b000SEvgeniy Ivanov movsb 398*58a2b000SEvgeniy Ivanov 399*58a2b000SEvgeniy Ivanov popl %edi 400*58a2b000SEvgeniy Ivanov popl %esi 401*58a2b000SEvgeniy Ivanov popl %ds 402*58a2b000SEvgeniy Ivanov popl %ebp 403*58a2b000SEvgeniy Ivanov ret 404*58a2b000SEvgeniy Ivanov 405*58a2b000SEvgeniy IvanovENTRY(vtophys) 406*58a2b000SEvgeniy Ivanov .code32 407*58a2b000SEvgeniy Ivanov movl _C_LABEL(ourseg), %eax 408*58a2b000SEvgeniy Ivanov shll $4, %eax 409*58a2b000SEvgeniy Ivanov addl 4(%esp), %eax 410*58a2b000SEvgeniy Ivanov ret 411*58a2b000SEvgeniy Ivanov 412*58a2b000SEvgeniy Ivanovmessage: 413*58a2b000SEvgeniy Ivanov .code16 414*58a2b000SEvgeniy Ivanov pushal 415*58a2b000SEvgeniy Ivanovmessage_1: 416*58a2b000SEvgeniy Ivanov cld 417*58a2b000SEvgeniy Ivanov1: lodsb 418*58a2b000SEvgeniy Ivanov testb %al, %al 419*58a2b000SEvgeniy Ivanov jz 2f 420*58a2b000SEvgeniy Ivanov movb $0xe, %ah 421*58a2b000SEvgeniy Ivanov movw $1, %bx 422*58a2b000SEvgeniy Ivanov int $0x10 423*58a2b000SEvgeniy Ivanov jmp 1b 424*58a2b000SEvgeniy Ivanov 425*58a2b000SEvgeniy Ivanov2: movb $0x86, %ah 426*58a2b000SEvgeniy Ivanov mov $16, %cx 427*58a2b000SEvgeniy Ivanov int $0x15 /* delay about a second */ 428*58a2b000SEvgeniy Ivanov popal 429*58a2b000SEvgeniy Ivanov ret 430*58a2b000SEvgeniy Ivanov 431*58a2b000SEvgeniy Ivanov/* These are useful for debugging 432*58a2b000SEvgeniy Ivanov */ 433*58a2b000SEvgeniy Ivanov .data 434*58a2b000SEvgeniy Ivanoveax_buf: 435*58a2b000SEvgeniy Ivanov .long 0, 0, 0, 0 436*58a2b000SEvgeniy Ivanov .text 437*58a2b000SEvgeniy IvanovENTRY(dump_eax) 438*58a2b000SEvgeniy Ivanov .code16 439*58a2b000SEvgeniy Ivanov pushal 440*58a2b000SEvgeniy Ivanov movw $eax_buf, %si 441*58a2b000SEvgeniy Ivanov mov %si, %di 442*58a2b000SEvgeniy Ivanov movw $8, %cx 443*58a2b000SEvgeniy Ivanov1: roll $4, %eax 444*58a2b000SEvgeniy Ivanov mov %ax, %bx 445*58a2b000SEvgeniy Ivanov andb $0x0f, %al 446*58a2b000SEvgeniy Ivanov addb $0x30, %al /* 30..3f - clear AF */ 447*58a2b000SEvgeniy Ivanov#if 1 /* 5 bytes to generate real hex... */ 448*58a2b000SEvgeniy Ivanov daa /* 30..39, 40..45 */ 449*58a2b000SEvgeniy Ivanov addb $0xc0, %al /* f0..f9, 00..05 */ 450*58a2b000SEvgeniy Ivanov adcb $0x40, %al /* 30..39, 41..45 */ 451*58a2b000SEvgeniy Ivanov#endif 452*58a2b000SEvgeniy Ivanov movb %al, (%di) /* %es != %ds, so can't ... */ 453*58a2b000SEvgeniy Ivanov inc %di /* ... use stosb */ 454*58a2b000SEvgeniy Ivanov mov %bx, %ax 455*58a2b000SEvgeniy Ivanov loop 1b 456*58a2b000SEvgeniy Ivanov movw $0x20, %ax /* space + null */ 457*58a2b000SEvgeniy Ivanov movw %ax, (%di) 458*58a2b000SEvgeniy Ivanov jmp message_1 459*58a2b000SEvgeniy Ivanov 460*58a2b000SEvgeniy Ivanov .globl _C_LABEL(trace_word) 461*58a2b000SEvgeniy Ivanov_C_LABEL(trace_word): 462*58a2b000SEvgeniy Ivanov .code32 463*58a2b000SEvgeniy Ivanov movl 4(%esp), %edx 464*58a2b000SEvgeniy Ivanov 465*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 466*58a2b000SEvgeniy Ivanov .code16 467*58a2b000SEvgeniy Ivanov movl %edx, %eax 468*58a2b000SEvgeniy Ivanov call dump_eax 469*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 470*58a2b000SEvgeniy Ivanov .code32 471*58a2b000SEvgeniy Ivanov ret 472*58a2b000SEvgeniy Ivanov 473*58a2b000SEvgeniy Ivanov .globl _C_LABEL(trace_str) 474*58a2b000SEvgeniy Ivanov_C_LABEL(trace_str): 475*58a2b000SEvgeniy Ivanov .code32 476*58a2b000SEvgeniy Ivanov pushl %esi 477*58a2b000SEvgeniy Ivanov 478*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 479*58a2b000SEvgeniy Ivanov .code16 480*58a2b000SEvgeniy Ivanov mov %sp, %si 481*58a2b000SEvgeniy Ivanov mov 8(%si), %si 482*58a2b000SEvgeniy Ivanov call message 483*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 484*58a2b000SEvgeniy Ivanov .code32 485*58a2b000SEvgeniy Ivanov popl %esi 486*58a2b000SEvgeniy Ivanov ret 487*58a2b000SEvgeniy Ivanov 488*58a2b000SEvgeniy Ivanov#ifdef XMS 489*58a2b000SEvgeniy Ivanov 490*58a2b000SEvgeniy Ivanov/* pointer to XMS driver, 0 if no XMS used */ 491*58a2b000SEvgeniy Ivanov 492*58a2b000SEvgeniy Ivanov .data 493*58a2b000SEvgeniy Ivanov_C_LABEL(xmsdrv): 494*58a2b000SEvgeniy Ivanov .long 0 495*58a2b000SEvgeniy Ivanov 496*58a2b000SEvgeniy Ivanov .text 497*58a2b000SEvgeniy IvanovENTRY(checkxms) 498*58a2b000SEvgeniy Ivanov .code32 499*58a2b000SEvgeniy Ivanov pushl %ebp 500*58a2b000SEvgeniy Ivanov movl %esp, %ebp 501*58a2b000SEvgeniy Ivanov pushl %ebx 502*58a2b000SEvgeniy Ivanov pushl %edx 503*58a2b000SEvgeniy Ivanov pushl %es 504*58a2b000SEvgeniy Ivanov pushl %esi 505*58a2b000SEvgeniy Ivanov pushl %edi 506*58a2b000SEvgeniy Ivanov 507*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 508*58a2b000SEvgeniy Ivanov .code16 509*58a2b000SEvgeniy Ivanov 510*58a2b000SEvgeniy Ivanov movw $0x4300, %ax 511*58a2b000SEvgeniy Ivanov int $0x2f /* check if XMS installed */ 512*58a2b000SEvgeniy Ivanov cmpb $0x80, %al 513*58a2b000SEvgeniy Ivanov jnz noxms 514*58a2b000SEvgeniy Ivanov 515*58a2b000SEvgeniy Ivanov movw $0x4310, %ax 516*58a2b000SEvgeniy Ivanov int $0x2f /* get driver address */ 517*58a2b000SEvgeniy Ivanov 518*58a2b000SEvgeniy Ivanov movw %bx, _C_LABEL(xmsdrv) /* save es:bx to _xmsdrv */ 519*58a2b000SEvgeniy Ivanov movw %es, _C_LABEL(xmsdrv) + 2 520*58a2b000SEvgeniy Ivanov 521*58a2b000SEvgeniy Ivanov movb $0x08, %ah /* XMS: query free extended memory */ 522*58a2b000SEvgeniy Ivanov#if 0 523*58a2b000SEvgeniy Ivanov movb $0x00, %bl 524*58a2b000SEvgeniy Ivanov#endif 525*58a2b000SEvgeniy Ivanov lcall *_C_LABEL(xmsdrv) 526*58a2b000SEvgeniy Ivanov jmp xdone 527*58a2b000SEvgeniy Ivanov 528*58a2b000SEvgeniy Ivanovnoxms: /* no XMS manager found */ 529*58a2b000SEvgeniy Ivanov mov $0, %dx 530*58a2b000SEvgeniy Ivanov 531*58a2b000SEvgeniy Ivanovxdone: 532*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 533*58a2b000SEvgeniy Ivanov .code32 534*58a2b000SEvgeniy Ivanov 535*58a2b000SEvgeniy Ivanov xorl %eax, %eax 536*58a2b000SEvgeniy Ivanov movw %dx, %ax 537*58a2b000SEvgeniy Ivanov 538*58a2b000SEvgeniy Ivanov popl %edi 539*58a2b000SEvgeniy Ivanov popl %esi 540*58a2b000SEvgeniy Ivanov popl %es 541*58a2b000SEvgeniy Ivanov popl %edx 542*58a2b000SEvgeniy Ivanov popl %ebx 543*58a2b000SEvgeniy Ivanov popl %ebp 544*58a2b000SEvgeniy Ivanov ret 545*58a2b000SEvgeniy Ivanov 546*58a2b000SEvgeniy Ivanov/* 547*58a2b000SEvgeniy Ivanov Allocate a block of XMS memory with the requested size 548*58a2b000SEvgeniy Ivanov void *xmsalloc(long int kBytes); 549*58a2b000SEvgeniy Ivanov 550*58a2b000SEvgeniy Ivanov Depends on _xmsdrv being set by getextmem() before first call 551*58a2b000SEvgeniy Ivanov to this function. 552*58a2b000SEvgeniy Ivanov 553*58a2b000SEvgeniy Ivanov Return value: a physical address. 554*58a2b000SEvgeniy Ivanov*/ 555*58a2b000SEvgeniy IvanovENTRY(xmsalloc) 556*58a2b000SEvgeniy Ivanov .code32 557*58a2b000SEvgeniy Ivanov pushl %ebp 558*58a2b000SEvgeniy Ivanov movl %esp, %ebp 559*58a2b000SEvgeniy Ivanov pushl %ebx 560*58a2b000SEvgeniy Ivanov pushl %edx 561*58a2b000SEvgeniy Ivanov pushl %esi 562*58a2b000SEvgeniy Ivanov pushl %edi 563*58a2b000SEvgeniy Ivanov 564*58a2b000SEvgeniy Ivanov movl 0x8(%ebp), %edx # Kbytes needed 565*58a2b000SEvgeniy Ivanov 566*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 567*58a2b000SEvgeniy Ivanov .code16 568*58a2b000SEvgeniy Ivanov 569*58a2b000SEvgeniy Ivanov movb $0x09, %ah # XMS allocate block 570*58a2b000SEvgeniy Ivanov lcall *_C_LABEL(xmsdrv) # result: handle in %dx 571*58a2b000SEvgeniy Ivanov movb $0x0c, %ah # XMS lock block 572*58a2b000SEvgeniy Ivanov lcall *_C_LABEL(xmsdrv) # result: 32 bit physical addr in DX:BX 573*58a2b000SEvgeniy Ivanov 574*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 575*58a2b000SEvgeniy Ivanov .code32 576*58a2b000SEvgeniy Ivanov 577*58a2b000SEvgeniy Ivanov movl %edx, %eax 578*58a2b000SEvgeniy Ivanov shl $16, %eax 579*58a2b000SEvgeniy Ivanov movw %bx, %ax # result in %eax 580*58a2b000SEvgeniy Ivanov 581*58a2b000SEvgeniy Ivanov popl %edi 582*58a2b000SEvgeniy Ivanov popl %esi 583*58a2b000SEvgeniy Ivanov popl %edx 584*58a2b000SEvgeniy Ivanov popl %ebx 585*58a2b000SEvgeniy Ivanov popl %ebp 586*58a2b000SEvgeniy Ivanov ret 587*58a2b000SEvgeniy Ivanov 588*58a2b000SEvgeniy Ivanov/* 589*58a2b000SEvgeniy Ivanov * ppbcopy(src, dst, cnt) 590*58a2b000SEvgeniy Ivanov * where src and dst are physical addresses 591*58a2b000SEvgeniy Ivanov */ 592*58a2b000SEvgeniy IvanovENTRY(ppbcopy) 593*58a2b000SEvgeniy Ivanov .code32 594*58a2b000SEvgeniy Ivanov pushl %ebp 595*58a2b000SEvgeniy Ivanov movl %esp, %ebp 596*58a2b000SEvgeniy Ivanov pushl %es 597*58a2b000SEvgeniy Ivanov pushl %esi 598*58a2b000SEvgeniy Ivanov pushl %edi 599*58a2b000SEvgeniy Ivanov 600*58a2b000SEvgeniy Ivanov cld 601*58a2b000SEvgeniy Ivanov 602*58a2b000SEvgeniy Ivanov # set %es to point at the flat segment 603*58a2b000SEvgeniy Ivanov movl $flatdataseg, %eax 604*58a2b000SEvgeniy Ivanov mov %ax, %es 605*58a2b000SEvgeniy Ivanov 606*58a2b000SEvgeniy Ivanov movl 8(%ebp), %esi # source 607*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edi # destination 608*58a2b000SEvgeniy Ivanov movl 16(%ebp), %ecx # count 609*58a2b000SEvgeniy Ivanov 610*58a2b000SEvgeniy Ivanov es 611*58a2b000SEvgeniy Ivanov rep 612*58a2b000SEvgeniy Ivanov movsb 613*58a2b000SEvgeniy Ivanov 614*58a2b000SEvgeniy Ivanov popl %edi 615*58a2b000SEvgeniy Ivanov popl %esi 616*58a2b000SEvgeniy Ivanov popl %es 617*58a2b000SEvgeniy Ivanov popl %ebp 618*58a2b000SEvgeniy Ivanov ret 619*58a2b000SEvgeniy Ivanov 620*58a2b000SEvgeniy Ivanov#endif 621