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