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