1/* $OpenBSD: srt0.S,v 1.1 2004/03/19 13:48:19 tom Exp $ */ 2 3/* 4 * Copyright (c) 1997 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29#include <machine/asm.h> 30#include <assym.h> 31 32#define BOOTSTACK 0xfffc 33 34 .globl _C_LABEL(end) 35 .globl _C_LABEL(edata) 36 .globl _C_LABEL(boot) 37 .globl _C_LABEL(_rtt) 38 .globl _C_LABEL(bios_bootdev) 39 .globl _ASM_LABEL(pmm_init) 40 .globl Gdtr 41 42 .text 43 .code16 44 .globl _start 45_start: 46#ifdef DEBUG 47 movl $0xb80a0, %ebx 48 addr32 movl $0x07420742, (%ebx) 49#endif 50 51/* Clobbers %ax, maybe more */ 52#define putc(c) movb $c, %al; call Lchr 53 54 /* 55 * We are loaded by the PXE loader at location 0x7C00. Like 56 * the standard /boot, we are linked to run at 0x40120 (load 57 * address 0x40000), so we relocate to there. 58 * 59 * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so don't 60 * have to worry about an overlapping copy until pxeboot is 61 * over 225 KB. 62 * 63 * Note that there are other reasons to be worried if 64 * sizeof(/boot) > 64 KB. So currently we copy a maximum of 64 KB. 65 * 66 * PXE loads us with a stack that grows down from 0x80000 (512 KB). 67 * While it is unlikely that this will clash with our code that 68 * we're copying up, we create a temporary stack just below us 69 * before the relocate. We also set the entire %esp register, to 70 * be on the safe side. 71 */ 72#define PXEBOOTADDR 0x7c00 /* Address where we are loaded by PXE */ 73 xorw %ax, %ax 74 movw %ax, %ss /* CPU disables interrupts till.. */ 75 movl $PXEBOOTADDR-4, %esp /* after this instruction */ 76 77 movw $(PXEBOOTADDR >> 4), %ax 78 movw %ax, %ds 79 xorw %si, %si /* Where we're coming from */ 80 81 movw $(LINKADDR >> 4), %ax 82 movw %ax, %es /* Set %es = 0x4000 */ 83 xorw %di, %di /* Where we're going to */ 84 85 movl $_C_LABEL(end), %ecx 86 subl $_C_LABEL(_start), %ecx /* How big are we? */ 87 88 cld 89 rep; movsb /* Copy into place */ 90 91 jmpl $(LINKADDR >> 4), $(relocated-_start) /* Now relocate */ 92 93relocated: 94 /* 95 * In 16-bit mode, we have segment registers == 0x4012, and 96 * offsets work from here, with offset(_start) == 0. 97 * 98 * In 32-bit mode, we have a flat memory model, where 99 * offset(_start) == 0x40120. This is how we're linked. 100 * 101 * Now transition to protected mode. 102 * 103 * First, initialise the global descriptor table. 104 */ 105 cli 106 push %cs 107 pop %ds 108 addr32 data32 lgdt (Gdtr - LINKADDR) 109 110 movl %cr0, %eax 111 orl $CR0_PE, %eax 112 data32 movl %eax, %cr0 113 data32 ljmp $8, $1f /* Seg sel 0x08 is flat 32-bit code */ 1141: 115 .code32 116 movl $0x10, %eax /* Seg sel 0x10 is flat 32-bit data */ 117 mov %ax, %ds 118 mov %ax, %es 119 mov %ax, %fs 120 mov %ax, %gs 121 mov %ax, %ss 122 movl $BOOTSTACK, %esp 123#ifdef DEBUG 124 movl $0xb8000, %ebx 125 movl $0x07420742, (%ebx) 126#endif 127 128 xorl %edx, %edx 129 movl %edx, _C_LABEL(bios_bootdev) 130 pushl %edx /* boot() takes this as a parameter */ 131 132 /* Set up an interrupt descriptor table for protected mode. */ 133 call _ASM_LABEL(pmm_init) 134#ifdef DEBUG 135 movl $0xb80a4, %ebx 136 movl $0x07520752, (%ebx) 137#endif 138 139 /* Zero .bss */ 140 xorl %eax, %eax 141 movl $_C_LABEL(end), %ecx 142 subl $_C_LABEL(edata), %ecx 143 movl $_C_LABEL(edata), %edi 144 cld 145 rep; stosb 146 147 /* Set our program name ("PXEBOOT", not "BOOT"). */ 148 movl $pxe_progname, %eax 149 movl %eax, progname 150 151 /* 152 * Now call "main()". 153 * 154 * We run in flat 32-bit protected mode, with no address mapping. 155 */ 156#ifdef DEBUG 157 movl $0xb8004, %ebx 158 movl $0x07410741, (%ebx) 159#endif 160 call _C_LABEL(boot) 161 162 /* boot() should not return. If it does, reset computer. */ 163 jmp _C_LABEL(_rtt) 164 165ENTRY(debugchar) 166 pushl %ebx 167 movl 8(%esp), %ebx 168 addl %ebx, %ebx 169 addl $0xb8000, %ebx 170 171 xorl %eax, %eax 172 movb 12(%esp), %al 173 174 andl $0xfffffffe, %ebx 175 movb %al, (%ebx) 176 popl %ebx 177 ret 178 179 .code16 180 181/* 182 * Write out value in %ax in hex 183 */ 184hex_word: 185 pushw %ax 186 mov %ah, %al 187 call hex_byte 188 popw %ax 189 /* fall thru */ 190/* 191 * Write out value in %al in hex 192 */ 193hex_byte: 194 pushw %ax 195 shrb $4, %al 196 call hex_nibble 197 popw %ax 198 /* fall thru */ 199 200/* Write out nibble in %al */ 201hex_nibble: 202 and $0x0F, %al 203 add $'0', %al 204 cmpb $'9', %al 205 jbe Lchr 206 addb $'A'-'9'-1, %al 207 /* fall thru to Lchr */ 208/* 209 * Lchr: write the character in %al to console 210 */ 211Lchr: 212 pushw %bx 213 movb $0x0e, %ah 214 xorw %bx, %bx 215 incw %bx /* movw $0x01, %bx */ 216 int $0x10 217 popw %bx 218 ret 219 220pxe_progname: 221 .asciz "PXEBOOT" 222 223 .end 224