start_pxe.S revision 1.1
1/* $NetBSD: start_pxe.S,v 1.1 2003/10/09 09:42:25 dsl Exp $ */ 2 3/* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * PXE startup 40 * parts from sys/arch/i386/stand/lib/crt/bootsect/start_bootsect.S 41 * 42 * See PXE SPEC 4.4.5 (pdf page 88) 43 */ 44 45#include <machine/asm.h> 46 47 .text 48ENTRY(start) 49 .code16 50 # start is loaded at 0x0:0x7c00 but we want 0x7c0:0x0 51 # ljmp to the next instruction to adjust %cs 52 ljmp $0x7c0, $start1 53 54 # Our stack XXX probably not! 55 .space 1024 56 57start1: 58 # set up %ds 59 xorl %eax, %eax 60 mov %cs, %ax 61 mov %ax, %ds 62 63 # set up %ss and %esp 64 mov %ax, %ss 65 movl $0xfffc, %esp /* stack at top of 64k segment */ 66 67 movl %eax, _C_LABEL(ourseg) 68 shll $4, %eax 69 70 /* fix up GDT entries for bootstrap */ 71#define FIXUP(gdt_index) \ 72 movw %ax, gdt+gdt_index+2; \ 73 movb %bl, gdt+gdt_index+4 74 75 shldl $16, %eax, %ebx 76 77 FIXUP(bootcodeseg) 78 FIXUP(bootrealseg) 79 FIXUP(bootdataseg) 80 81 /* fix up GDT pointer */ 82 addl $gdt, %eax 83 movl %eax, gdtarg+2 84 85 /* change to protected mode */ 86 calll _C_LABEL(real_to_prot) 87 .code32 88 89 /* clear bss */ 90 xorl %eax, %eax 91 movl $_C_LABEL(edata), %edi 92 movl $_C_LABEL(end), %ecx 93 subl %edi, %ecx 94 cld 95 rep 96 stosb 97 98 /* ...and call main()! */ 99 call _C_LABEL(main) 100 101 .globl _C_LABEL(exit) 102_C_LABEL(exit): 103 call _C_LABEL(prot_to_real) 104 .code16 105 movw $efail, %si 106 call message 107 108#ifdef notyet 109 /* sleep for 3s = 0x2dc6c0 us */ 110 movb $0x86, %ah 111 mov $0x002d, %cx 112 mov $0xc6c0, %dx 113 int $0x15 114 115 /* call ROM BASIC */ 116 int $0x18 117#else 118 cli 119 hlt 120#endif 121 122efail: .asciz "Boot fail\r\n" 123 124ENTRY(ourseg) 125 .long 0 126 127/************************************************************************** 128GLOBAL DESCRIPTOR TABLE 129**************************************************************************/ 130#ifdef __ELF__ 131 .align 16 132#else 133 .align 4 134#endif 135gdt: 136 .word 0, 0 137 .byte 0, 0x00, 0x00, 0 138 139#ifdef SUPPORT_LINUX /* additional dummy */ 140 .word 0, 0 141 .byte 0, 0x00, 0x00, 0 142#endif 143 144 /* kernel code segment */ 145 .globl flatcodeseg 146flatcodeseg = . - gdt 147 .word 0xffff, 0 148 .byte 0, 0x9f, 0xcf, 0 149 150 /* kernel data segment */ 151 .globl flatdataseg 152flatdataseg = . - gdt 153 .word 0xffff, 0 154 .byte 0, 0x93, 0xcf, 0 155 156 /* boot code segment, base will be patched */ 157bootcodeseg = . - gdt 158 .word 0xffff, 0 159 .byte 0, 0x9e, 0x4f, 0 160 161 /* boot data segment, base will be patched */ 162bootdataseg = . - gdt 163 .word 0xffff, 0 164 .byte 0, 0x92, 0x4f, 0 165 166 /* 16 bit real mode, base will be patched */ 167bootrealseg = . - gdt 168 .word 0xffff, 0 169 .byte 0, 0x9e, 0x00, 0 170 171 /* limits (etc) for data segment in real mode */ 172bootrealdata = . - gdt 173 .word 0xffff, 0 174 .byte 0, 0x92, 0x00, 0 175gdtlen = . - gdt 176 177#ifdef __ELF__ 178 .align 16 179#else 180 .align 4 181#endif 182gdtarg: 183 .word gdtlen-1 /* limit */ 184 .long 0 /* addr, will be inserted */ 185 186CR0_PE = 0x1 187 188/* 189 * real_to_prot() 190 * transfer from real mode to protected mode. 191 */ 192ENTRY(real_to_prot) 193 .code16 194 # guarantee that interrupt is disabled when in prot mode 195 cli 196 pushl %eax 197 push %cs /* ensure %ds is correct */ 198 pop %ds 199 200 # load the gdtr 201 lgdt gdtarg 202 203 # set the PE bit of CR0 204 movl %cr0, %eax 205 206 orl $CR0_PE, %eax 207 movl %eax, %cr0 208 209 # make intrasegment jump to flush the processor pipeline and 210 # reload CS register 211 ljmp $bootcodeseg, $xprot 212 213xprot: 214 .code32 215 # we are in USE32 mode now 216 # set up the protected mode segment registers : DS, SS, ES 217 mov $bootdataseg, %ax 218 mov %ax, %ds 219 mov %ax, %ss 220 mov %ax, %es 221 222 popl %eax 223 ret 224 225/* 226 * prot_to_real() 227 * transfer from protected mode to real mode 228 */ 229ENTRY(prot_to_real) 230 .code32 231 pushl %eax 232 # set up a dummy stack frame for the second seg change. 233 # Adjust the intersegment jump instruction following 234 # the clearing of protected mode bit. 235 # This is self-modifying code, but we need a writable 236 # code segment, and an intersegment return does not give us that. 237 238 movl _C_LABEL(ourseg), %eax 239 movw %ax, xreal-2 240 241 /* 242 * Load the segment registers while still in protected mode. 243 * Otherwise the control bits don't get changed. 244 * The correct values are loaded later. 245 */ 246 movw $bootrealdata, %ax 247 movw %ax, %ds 248 movw %ax, %es 249 movw %ax, %ss 250 251 # Change to use16 mode. 252 ljmp $bootrealseg, $x16 253 254x16: 255 .code16 256 # clear the PE bit of CR0 257 movl %cr0, %eax 258 andl $~CR0_PE, %eax 259 movl %eax, %cr0 260 ljmp $0, $xreal /* segment overwritten above */ 261 262xreal: 263 .code16 264 # we are in real mode now 265 # set up the real mode segment registers : DS, SS, ES 266 mov %cs, %ax 267 mov %ax, %ds 268 mov %ax, %ss 269 mov %ax, %es 270 271 sti 272 popl %eax 273 retl 274 275/* 276 * pbzero(dst, cnt) 277 * where dst is a physical address and cnt is the length 278 */ 279ENTRY(pbzero) 280 .code32 281 pushl %ebp 282 movl %esp, %ebp 283 pushl %es 284 pushl %edi 285 286 cld 287 288 # set %es to point at the flat segment 289 movl $flatdataseg, %eax 290 mov %ax, %es 291 292 movl 8(%ebp), %edi # destination 293 movl 12(%ebp), %ecx # count 294 xorl %eax, %eax # value 295 296 rep 297 stosb 298 299 popl %edi 300 popl %es 301 popl %ebp 302 ret 303 304/* 305 * vpbcopy(src, dst, cnt) 306 * where src is a virtual address and dst is a physical address 307 */ 308ENTRY(vpbcopy) 309 .code32 310 pushl %ebp 311 movl %esp, %ebp 312 pushl %es 313 pushl %esi 314 pushl %edi 315 316 cld 317 318 # set %es to point at the flat segment 319 movl $flatdataseg, %eax 320 mov %ax, %es 321 322 movl 8(%ebp), %esi # source 323 movl 12(%ebp), %edi # destination 324 movl 16(%ebp), %ecx # count 325 326 rep 327 movsb 328 329 popl %edi 330 popl %esi 331 popl %es 332 popl %ebp 333 ret 334 335/* 336 * pvbcopy(src, dst, cnt) 337 * where src is a physical address and dst is a virtual address 338 */ 339ENTRY(pvbcopy) 340 .code32 341 pushl %ebp 342 movl %esp, %ebp 343 pushl %ds 344 pushl %esi 345 pushl %edi 346 347 cld 348 349 # set %ds to point at the flat segment 350 movl $flatdataseg, %eax 351 mov %ax, %ds 352 353 movl 8(%ebp), %esi # source 354 movl 12(%ebp), %edi # destination 355 movl 16(%ebp), %ecx # count 356 357 rep 358 movsb 359 360 popl %edi 361 popl %esi 362 popl %ds 363 popl %ebp 364 ret 365 366ENTRY(vtophys) 367 movl _C_LABEL(ourseg), %eax 368 shll $4, %eax 369 addl 4(%esp), %eax 370 ret 371 372/* 373 * message: write the error message in %ds:%esi to the console 374 */ 375message: 376 .code16 377/* 378 * BIOS call "INT 10H Function 0Eh" to write character to console 379 * Call with %ah = 0x0e 380 * %al = character 381 * %bh = page 382 * %bl = foreground color 383 */ 384 pushl %eax 385 pushl %ebx 386 pushl %edx 387 388nextb: 389 cld 390 lodsb # load a byte into %al 391 testb %al, %al 392 jz done 393 394 movb $0x0e, %ah 395 movw $0x0001, %bx 396 int $0x10 397 398 jmp nextb 399 400done: 401 popl %edx 402 popl %ebx 403 popl %eax 404 ret 405