1/* $OpenBSD: srt0.S,v 1.4 2022/12/08 01:25:45 guenther 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 end 35 .globl edata 36 .globl boot 37 .globl _rtt 38 .globl bios_bootdev 39 .globl 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 operate as a no emulation boot image, as defined by the 56 * El Torito Bootable CD-ROM Format Specification v1.0. We use 57 * a load segment of 0x07C0 (physical load address of 0x7C00). 58 * Like the standard /boot, we are linked to run at 0x40120 59 * (load address 0x40000), so we relocate to there. 60 * 61 * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so we don't 62 * have to worry about an overlapping copy until cdboot is 63 * over 225 KB. 64 * 65 * Our cdbr CD-ROM boot sector passes us the drive number to use 66 * in %dl. 67 */ 68#define CDBOOTADDR 0x7c00 /* Address where BIOS loads up */ 69 xorw %ax, %ax 70 movw %ax, %ss /* CPU disables interrupts till... */ 71 movl $CDBOOTADDR-4, %esp /* after this instruction */ 72 73 pushl %edx /* Preserve the drive number. */ 74 75 movw $(CDBOOTADDR >> 4), %ax /* Reloc from %ds = 0x7c0. */ 76 movw $(LINKADDR >> 4), %bx /* Reloc to %es = 0x4012. */ 77 78 movl $end, %edx 79 subl $_start, %edx /* How big are we? */ 80 81 /* 82 * Relocate in blocks that are a maximum of 32KB in size, incrementing 83 * the segment registers after each block. The 'rep; movsb' instruction 84 * uses %cx, which limits us to a maximum block size of 0xfff0, even 85 * though we can address the full 64KB within a single segment. 86 */ 87#define RELOC_BLOCK_SIZE 0x8000 88reloc_loop: 89 movl %edx, %ecx 90 jcxz reloc_done 91 cmpl $RELOC_BLOCK_SIZE, %ecx 92 jbe reloc_notrunc 93 movl $RELOC_BLOCK_SIZE, %ecx 94reloc_notrunc: 95 subl %ecx, %edx 96 97 movw %ax, %ds /* Where we're coming from */ 98 xorw %si, %si 99 100 movw %bx, %es /* Where we're going to */ 101 xorw %di, %di 102 103 cld 104 rep; movsb /* Copy into place */ 105 106 addw $(RELOC_BLOCK_SIZE >> 4), %ax 107 addw $(RELOC_BLOCK_SIZE >> 4), %bx 108 109 jmp reloc_loop 110 111reloc_done: 112 popl %edx 113 jmpl $(LINKADDR >> 4), $(relocated-_start) /* Now relocate */ 114 115relocated: 116 /* 117 * In 16-bit mode, we have segment registers == 0x4012, and 118 * offsets work from here, with offset(_start) == 0. 119 * 120 * In 32-bit mode, we have a flat memory model, where 121 * offset(_start) == 0x40120. This is how we're linked. 122 * 123 * Now transition to protected mode. 124 * 125 * First, initialise the global descriptor table. 126 */ 127 cli 128 push %cs 129 pop %ds 130 addr32 data32 lgdt (Gdtr - LINKADDR) 131 132 movl %cr0, %eax 133 orl $CR0_PE, %eax 134 data32 movl %eax, %cr0 135 data32 ljmp $8, $1f /* Seg sel 0x08 is flat 32-bit code */ 1361: 137 .code32 138 movl $0x10, %eax /* Seg sel 0x10 is flat 32-bit data */ 139 mov %ax, %ds 140 mov %ax, %es 141 mov %ax, %fs 142 mov %ax, %gs 143 mov %ax, %ss 144 movl $BOOTSTACK, %esp 145#ifdef DEBUG 146 movl $0xb8000, %ebx 147 movl $0x07420742, (%ebx) 148#endif 149 150 movzbl %dl, %eax 151 orl $0x100, %eax /* Indicate that it's a cd device */ 152 pushl %eax /* boot() takes this as a parameter */ 153 154#ifdef DEBUG 155 movl $0xb80a4, %ebx 156 movl $0x07520752, (%ebx) 157#endif 158 159 /* Zero .bss */ 160 xorl %eax, %eax 161 movl $end, %ecx 162 subl $edata, %ecx 163 movl $edata, %edi 164 cld 165 rep; stosb 166 167 /* Set up an interrupt descriptor table for protected mode. */ 168 call pmm_init 169 170 /* Set our program name ("CDBOOT", not "BOOT"). */ 171 movl $cd_progname, %eax 172 movl %eax, progname 173 174 /* Put the boot device number into the globals that need it */ 175 popl %eax /* Get this back from the stack */ 176 pushl %eax /* boot() takes this as a parameter */ 177 movl %eax, bios_bootdev 178 movl %eax, bios_cddev 179 180 /* 181 * Now call "main()". 182 * 183 * We run in flat 32-bit protected mode, with no address mapping. 184 */ 185#ifdef DEBUG 186 movl $0xb8004, %ebx 187 movl $0x07410741, (%ebx) 188#endif 189 call boot 190 191 /* boot() should not return. If it does, reset computer. */ 192 jmp _rtt 193 194ENTRY(debugchar) 195 pushl %ebx 196 movl 8(%esp), %ebx 197 addl %ebx, %ebx 198 addl $0xb8000, %ebx 199 200 xorl %eax, %eax 201 movb 12(%esp), %al 202 203 andl $0xfffffffe, %ebx 204 movb %al, (%ebx) 205 popl %ebx 206 ret 207 208 .code16 209 210/* 211 * Display ASCIZ string at %si. Trashes %si. 212 */ 213Lstr: 214 pushw %ax 215 cld 2161: 217 lodsb /* %al = *%si++ */ 218 testb %al, %al 219 jz 1f 220 call Lchr 221 jmp 1b 2221: popw %ax 223 ret 224 225/* 226 * Write out value in %ax in hex 227 */ 228hex_word: 229 pushw %ax 230 mov %ah, %al 231 call hex_byte 232 popw %ax 233 /* fall thru */ 234/* 235 * Write out value in %al in hex 236 */ 237hex_byte: 238 pushw %ax 239 shrb $4, %al 240 call hex_nibble 241 popw %ax 242 /* fall thru */ 243 244/* Write out nibble in %al */ 245hex_nibble: 246 and $0x0F, %al 247 add $'0', %al 248 cmpb $'9', %al 249 jbe Lchr 250 addb $'A'-'9'-1, %al 251 /* fall thru to Lchr */ 252/* 253 * Lchr: write the character in %al to console 254 */ 255Lchr: 256 pushw %bx 257 movb $0x0e, %ah 258 xorw %bx, %bx 259 incw %bx /* movw $0x01, %bx */ 260 int $0x10 261 popw %bx 262 ret 263 264cd_progname: 265 .asciz "CDBOOT" 266 267 .end 268