start_pxe.S revision 1.1
11.1Sdsl/* $NetBSD: start_pxe.S,v 1.1 2003/10/09 09:42:25 dsl Exp $ */ 21.1Sdsl 31.1Sdsl/* 41.1Sdsl * Copyright 2001 Wasabi Systems, Inc. 51.1Sdsl * All rights reserved. 61.1Sdsl * 71.1Sdsl * Written by Jason R. Thorpe for Wasabi Systems, Inc. 81.1Sdsl * 91.1Sdsl * Redistribution and use in source and binary forms, with or without 101.1Sdsl * modification, are permitted provided that the following conditions 111.1Sdsl * are met: 121.1Sdsl * 1. Redistributions of source code must retain the above copyright 131.1Sdsl * notice, this list of conditions and the following disclaimer. 141.1Sdsl * 2. Redistributions in binary form must reproduce the above copyright 151.1Sdsl * notice, this list of conditions and the following disclaimer in the 161.1Sdsl * documentation and/or other materials provided with the distribution. 171.1Sdsl * 3. All advertising materials mentioning features or use of this software 181.1Sdsl * must display the following acknowledgement: 191.1Sdsl * This product includes software developed for the NetBSD Project by 201.1Sdsl * Wasabi Systems, Inc. 211.1Sdsl * 4. The name of Wasabi Systems, Inc. may not be used to endorse 221.1Sdsl * or promote products derived from this software without specific prior 231.1Sdsl * written permission. 241.1Sdsl * 251.1Sdsl * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 261.1Sdsl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 271.1Sdsl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 281.1Sdsl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 291.1Sdsl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301.1Sdsl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311.1Sdsl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 321.1Sdsl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 331.1Sdsl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 341.1Sdsl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 351.1Sdsl * POSSIBILITY OF SUCH DAMAGE. 361.1Sdsl */ 371.1Sdsl 381.1Sdsl/* 391.1Sdsl * PXE startup 401.1Sdsl * parts from sys/arch/i386/stand/lib/crt/bootsect/start_bootsect.S 411.1Sdsl * 421.1Sdsl * See PXE SPEC 4.4.5 (pdf page 88) 431.1Sdsl */ 441.1Sdsl 451.1Sdsl#include <machine/asm.h> 461.1Sdsl 471.1Sdsl .text 481.1SdslENTRY(start) 491.1Sdsl .code16 501.1Sdsl # start is loaded at 0x0:0x7c00 but we want 0x7c0:0x0 511.1Sdsl # ljmp to the next instruction to adjust %cs 521.1Sdsl ljmp $0x7c0, $start1 531.1Sdsl 541.1Sdsl # Our stack XXX probably not! 551.1Sdsl .space 1024 561.1Sdsl 571.1Sdslstart1: 581.1Sdsl # set up %ds 591.1Sdsl xorl %eax, %eax 601.1Sdsl mov %cs, %ax 611.1Sdsl mov %ax, %ds 621.1Sdsl 631.1Sdsl # set up %ss and %esp 641.1Sdsl mov %ax, %ss 651.1Sdsl movl $0xfffc, %esp /* stack at top of 64k segment */ 661.1Sdsl 671.1Sdsl movl %eax, _C_LABEL(ourseg) 681.1Sdsl shll $4, %eax 691.1Sdsl 701.1Sdsl /* fix up GDT entries for bootstrap */ 711.1Sdsl#define FIXUP(gdt_index) \ 721.1Sdsl movw %ax, gdt+gdt_index+2; \ 731.1Sdsl movb %bl, gdt+gdt_index+4 741.1Sdsl 751.1Sdsl shldl $16, %eax, %ebx 761.1Sdsl 771.1Sdsl FIXUP(bootcodeseg) 781.1Sdsl FIXUP(bootrealseg) 791.1Sdsl FIXUP(bootdataseg) 801.1Sdsl 811.1Sdsl /* fix up GDT pointer */ 821.1Sdsl addl $gdt, %eax 831.1Sdsl movl %eax, gdtarg+2 841.1Sdsl 851.1Sdsl /* change to protected mode */ 861.1Sdsl calll _C_LABEL(real_to_prot) 871.1Sdsl .code32 881.1Sdsl 891.1Sdsl /* clear bss */ 901.1Sdsl xorl %eax, %eax 911.1Sdsl movl $_C_LABEL(edata), %edi 921.1Sdsl movl $_C_LABEL(end), %ecx 931.1Sdsl subl %edi, %ecx 941.1Sdsl cld 951.1Sdsl rep 961.1Sdsl stosb 971.1Sdsl 981.1Sdsl /* ...and call main()! */ 991.1Sdsl call _C_LABEL(main) 1001.1Sdsl 1011.1Sdsl .globl _C_LABEL(exit) 1021.1Sdsl_C_LABEL(exit): 1031.1Sdsl call _C_LABEL(prot_to_real) 1041.1Sdsl .code16 1051.1Sdsl movw $efail, %si 1061.1Sdsl call message 1071.1Sdsl 1081.1Sdsl#ifdef notyet 1091.1Sdsl /* sleep for 3s = 0x2dc6c0 us */ 1101.1Sdsl movb $0x86, %ah 1111.1Sdsl mov $0x002d, %cx 1121.1Sdsl mov $0xc6c0, %dx 1131.1Sdsl int $0x15 1141.1Sdsl 1151.1Sdsl /* call ROM BASIC */ 1161.1Sdsl int $0x18 1171.1Sdsl#else 1181.1Sdsl cli 1191.1Sdsl hlt 1201.1Sdsl#endif 1211.1Sdsl 1221.1Sdslefail: .asciz "Boot fail\r\n" 1231.1Sdsl 1241.1SdslENTRY(ourseg) 1251.1Sdsl .long 0 1261.1Sdsl 1271.1Sdsl/************************************************************************** 1281.1SdslGLOBAL DESCRIPTOR TABLE 1291.1Sdsl**************************************************************************/ 1301.1Sdsl#ifdef __ELF__ 1311.1Sdsl .align 16 1321.1Sdsl#else 1331.1Sdsl .align 4 1341.1Sdsl#endif 1351.1Sdslgdt: 1361.1Sdsl .word 0, 0 1371.1Sdsl .byte 0, 0x00, 0x00, 0 1381.1Sdsl 1391.1Sdsl#ifdef SUPPORT_LINUX /* additional dummy */ 1401.1Sdsl .word 0, 0 1411.1Sdsl .byte 0, 0x00, 0x00, 0 1421.1Sdsl#endif 1431.1Sdsl 1441.1Sdsl /* kernel code segment */ 1451.1Sdsl .globl flatcodeseg 1461.1Sdslflatcodeseg = . - gdt 1471.1Sdsl .word 0xffff, 0 1481.1Sdsl .byte 0, 0x9f, 0xcf, 0 1491.1Sdsl 1501.1Sdsl /* kernel data segment */ 1511.1Sdsl .globl flatdataseg 1521.1Sdslflatdataseg = . - gdt 1531.1Sdsl .word 0xffff, 0 1541.1Sdsl .byte 0, 0x93, 0xcf, 0 1551.1Sdsl 1561.1Sdsl /* boot code segment, base will be patched */ 1571.1Sdslbootcodeseg = . - gdt 1581.1Sdsl .word 0xffff, 0 1591.1Sdsl .byte 0, 0x9e, 0x4f, 0 1601.1Sdsl 1611.1Sdsl /* boot data segment, base will be patched */ 1621.1Sdslbootdataseg = . - gdt 1631.1Sdsl .word 0xffff, 0 1641.1Sdsl .byte 0, 0x92, 0x4f, 0 1651.1Sdsl 1661.1Sdsl /* 16 bit real mode, base will be patched */ 1671.1Sdslbootrealseg = . - gdt 1681.1Sdsl .word 0xffff, 0 1691.1Sdsl .byte 0, 0x9e, 0x00, 0 1701.1Sdsl 1711.1Sdsl /* limits (etc) for data segment in real mode */ 1721.1Sdslbootrealdata = . - gdt 1731.1Sdsl .word 0xffff, 0 1741.1Sdsl .byte 0, 0x92, 0x00, 0 1751.1Sdslgdtlen = . - gdt 1761.1Sdsl 1771.1Sdsl#ifdef __ELF__ 1781.1Sdsl .align 16 1791.1Sdsl#else 1801.1Sdsl .align 4 1811.1Sdsl#endif 1821.1Sdslgdtarg: 1831.1Sdsl .word gdtlen-1 /* limit */ 1841.1Sdsl .long 0 /* addr, will be inserted */ 1851.1Sdsl 1861.1SdslCR0_PE = 0x1 1871.1Sdsl 1881.1Sdsl/* 1891.1Sdsl * real_to_prot() 1901.1Sdsl * transfer from real mode to protected mode. 1911.1Sdsl */ 1921.1SdslENTRY(real_to_prot) 1931.1Sdsl .code16 1941.1Sdsl # guarantee that interrupt is disabled when in prot mode 1951.1Sdsl cli 1961.1Sdsl pushl %eax 1971.1Sdsl push %cs /* ensure %ds is correct */ 1981.1Sdsl pop %ds 1991.1Sdsl 2001.1Sdsl # load the gdtr 2011.1Sdsl lgdt gdtarg 2021.1Sdsl 2031.1Sdsl # set the PE bit of CR0 2041.1Sdsl movl %cr0, %eax 2051.1Sdsl 2061.1Sdsl orl $CR0_PE, %eax 2071.1Sdsl movl %eax, %cr0 2081.1Sdsl 2091.1Sdsl # make intrasegment jump to flush the processor pipeline and 2101.1Sdsl # reload CS register 2111.1Sdsl ljmp $bootcodeseg, $xprot 2121.1Sdsl 2131.1Sdslxprot: 2141.1Sdsl .code32 2151.1Sdsl # we are in USE32 mode now 2161.1Sdsl # set up the protected mode segment registers : DS, SS, ES 2171.1Sdsl mov $bootdataseg, %ax 2181.1Sdsl mov %ax, %ds 2191.1Sdsl mov %ax, %ss 2201.1Sdsl mov %ax, %es 2211.1Sdsl 2221.1Sdsl popl %eax 2231.1Sdsl ret 2241.1Sdsl 2251.1Sdsl/* 2261.1Sdsl * prot_to_real() 2271.1Sdsl * transfer from protected mode to real mode 2281.1Sdsl */ 2291.1SdslENTRY(prot_to_real) 2301.1Sdsl .code32 2311.1Sdsl pushl %eax 2321.1Sdsl # set up a dummy stack frame for the second seg change. 2331.1Sdsl # Adjust the intersegment jump instruction following 2341.1Sdsl # the clearing of protected mode bit. 2351.1Sdsl # This is self-modifying code, but we need a writable 2361.1Sdsl # code segment, and an intersegment return does not give us that. 2371.1Sdsl 2381.1Sdsl movl _C_LABEL(ourseg), %eax 2391.1Sdsl movw %ax, xreal-2 2401.1Sdsl 2411.1Sdsl /* 2421.1Sdsl * Load the segment registers while still in protected mode. 2431.1Sdsl * Otherwise the control bits don't get changed. 2441.1Sdsl * The correct values are loaded later. 2451.1Sdsl */ 2461.1Sdsl movw $bootrealdata, %ax 2471.1Sdsl movw %ax, %ds 2481.1Sdsl movw %ax, %es 2491.1Sdsl movw %ax, %ss 2501.1Sdsl 2511.1Sdsl # Change to use16 mode. 2521.1Sdsl ljmp $bootrealseg, $x16 2531.1Sdsl 2541.1Sdslx16: 2551.1Sdsl .code16 2561.1Sdsl # clear the PE bit of CR0 2571.1Sdsl movl %cr0, %eax 2581.1Sdsl andl $~CR0_PE, %eax 2591.1Sdsl movl %eax, %cr0 2601.1Sdsl ljmp $0, $xreal /* segment overwritten above */ 2611.1Sdsl 2621.1Sdslxreal: 2631.1Sdsl .code16 2641.1Sdsl # we are in real mode now 2651.1Sdsl # set up the real mode segment registers : DS, SS, ES 2661.1Sdsl mov %cs, %ax 2671.1Sdsl mov %ax, %ds 2681.1Sdsl mov %ax, %ss 2691.1Sdsl mov %ax, %es 2701.1Sdsl 2711.1Sdsl sti 2721.1Sdsl popl %eax 2731.1Sdsl retl 2741.1Sdsl 2751.1Sdsl/* 2761.1Sdsl * pbzero(dst, cnt) 2771.1Sdsl * where dst is a physical address and cnt is the length 2781.1Sdsl */ 2791.1SdslENTRY(pbzero) 2801.1Sdsl .code32 2811.1Sdsl pushl %ebp 2821.1Sdsl movl %esp, %ebp 2831.1Sdsl pushl %es 2841.1Sdsl pushl %edi 2851.1Sdsl 2861.1Sdsl cld 2871.1Sdsl 2881.1Sdsl # set %es to point at the flat segment 2891.1Sdsl movl $flatdataseg, %eax 2901.1Sdsl mov %ax, %es 2911.1Sdsl 2921.1Sdsl movl 8(%ebp), %edi # destination 2931.1Sdsl movl 12(%ebp), %ecx # count 2941.1Sdsl xorl %eax, %eax # value 2951.1Sdsl 2961.1Sdsl rep 2971.1Sdsl stosb 2981.1Sdsl 2991.1Sdsl popl %edi 3001.1Sdsl popl %es 3011.1Sdsl popl %ebp 3021.1Sdsl ret 3031.1Sdsl 3041.1Sdsl/* 3051.1Sdsl * vpbcopy(src, dst, cnt) 3061.1Sdsl * where src is a virtual address and dst is a physical address 3071.1Sdsl */ 3081.1SdslENTRY(vpbcopy) 3091.1Sdsl .code32 3101.1Sdsl pushl %ebp 3111.1Sdsl movl %esp, %ebp 3121.1Sdsl pushl %es 3131.1Sdsl pushl %esi 3141.1Sdsl pushl %edi 3151.1Sdsl 3161.1Sdsl cld 3171.1Sdsl 3181.1Sdsl # set %es to point at the flat segment 3191.1Sdsl movl $flatdataseg, %eax 3201.1Sdsl mov %ax, %es 3211.1Sdsl 3221.1Sdsl movl 8(%ebp), %esi # source 3231.1Sdsl movl 12(%ebp), %edi # destination 3241.1Sdsl movl 16(%ebp), %ecx # count 3251.1Sdsl 3261.1Sdsl rep 3271.1Sdsl movsb 3281.1Sdsl 3291.1Sdsl popl %edi 3301.1Sdsl popl %esi 3311.1Sdsl popl %es 3321.1Sdsl popl %ebp 3331.1Sdsl ret 3341.1Sdsl 3351.1Sdsl/* 3361.1Sdsl * pvbcopy(src, dst, cnt) 3371.1Sdsl * where src is a physical address and dst is a virtual address 3381.1Sdsl */ 3391.1SdslENTRY(pvbcopy) 3401.1Sdsl .code32 3411.1Sdsl pushl %ebp 3421.1Sdsl movl %esp, %ebp 3431.1Sdsl pushl %ds 3441.1Sdsl pushl %esi 3451.1Sdsl pushl %edi 3461.1Sdsl 3471.1Sdsl cld 3481.1Sdsl 3491.1Sdsl # set %ds to point at the flat segment 3501.1Sdsl movl $flatdataseg, %eax 3511.1Sdsl mov %ax, %ds 3521.1Sdsl 3531.1Sdsl movl 8(%ebp), %esi # source 3541.1Sdsl movl 12(%ebp), %edi # destination 3551.1Sdsl movl 16(%ebp), %ecx # count 3561.1Sdsl 3571.1Sdsl rep 3581.1Sdsl movsb 3591.1Sdsl 3601.1Sdsl popl %edi 3611.1Sdsl popl %esi 3621.1Sdsl popl %ds 3631.1Sdsl popl %ebp 3641.1Sdsl ret 3651.1Sdsl 3661.1SdslENTRY(vtophys) 3671.1Sdsl movl _C_LABEL(ourseg), %eax 3681.1Sdsl shll $4, %eax 3691.1Sdsl addl 4(%esp), %eax 3701.1Sdsl ret 3711.1Sdsl 3721.1Sdsl/* 3731.1Sdsl * message: write the error message in %ds:%esi to the console 3741.1Sdsl */ 3751.1Sdslmessage: 3761.1Sdsl .code16 3771.1Sdsl/* 3781.1Sdsl * BIOS call "INT 10H Function 0Eh" to write character to console 3791.1Sdsl * Call with %ah = 0x0e 3801.1Sdsl * %al = character 3811.1Sdsl * %bh = page 3821.1Sdsl * %bl = foreground color 3831.1Sdsl */ 3841.1Sdsl pushl %eax 3851.1Sdsl pushl %ebx 3861.1Sdsl pushl %edx 3871.1Sdsl 3881.1Sdslnextb: 3891.1Sdsl cld 3901.1Sdsl lodsb # load a byte into %al 3911.1Sdsl testb %al, %al 3921.1Sdsl jz done 3931.1Sdsl 3941.1Sdsl movb $0x0e, %ah 3951.1Sdsl movw $0x0001, %bx 3961.1Sdsl int $0x10 3971.1Sdsl 3981.1Sdsl jmp nextb 3991.1Sdsl 4001.1Sdsldone: 4011.1Sdsl popl %edx 4021.1Sdsl popl %ebx 4031.1Sdsl popl %eax 4041.1Sdsl ret 405