/*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)wdbootblk.c 7.1 (Berkeley) 4/28/91 */ /* * wdbootblk.s: * Written 7/6/90 by William F. Jolitz * Initial block boot for AT/386 with typical Western Digital * WD 1002-WA2 (or upwards compatable). Works either as * first and sole partition bootstrap, or as loaded by a * earlier BIOS boot when on an inner partition of the disk. * * Goal is to read in sucessive 7.5Kbytes of bootstrap to * execute. * * No attempt is made to handle disk errors. */ #include "i386/isa/isa.h" #include "i386/isa/wdreg.h" #define NOP inb $0x84,%al #define BIOSRELOC 0x7c00 #define start RELOC+0x400 /* step 0 force descriptors to bottom of address space */ cli .byte 0xb8,0x30,0x00 /* mov $0x30,%ax */ mov %ax, %ss .byte 0xbc,0x00,0x01 /* mov $0x100,%sp */ xorl %eax,%eax movl %ax,%ds movl %ax,%es /* obtain BIOS parameters for hard disk XXX */ movb $0x9f,%ah /* write to 0x9ff00 XXX */ movb $0xf0,%al mov %ax,%es xor %edi,%edi .byte 0xf, 0xb4, 0x36 ; .word 0x41*4 /* lfs 0x41*4, %si */ xorb %ch,%ch movb $0x10,%cl fs rep movsb .byte 0xf, 0xb4, 0x36 ; .word 0x46*4 /* lfs 0x46*4, %si */ xorb %ch,%ch movb $0x10,%cl fs rep movsb xorl %eax,%eax movl %ax,%es /* step 1 load new descriptor table */ .byte 0x3E,0x0F,1,0x16 .word BIOSRELOC+0x6e #GDTptr # word aword cs lgdt GDTptr /* step 2 turn on protected mode */ smsw %ax orb $1,%al lmsw %ax jmp 1f nop /* step 3 reload segment descriptors */ 1: xorl %eax,%eax movb $0x10,%al movl %ax,%ds movl %ax,%es movl %ax,%ss word ljmp $0x8,$ BIOSRELOC+0x74 /* would be nice if .-RELOC+0x7c00 worked */ /* Global Descriptor Table contains three descriptors: * 0x00: Null: not used * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes * (overlays code) */ GDT: NullDesc: .word 0,0,0,0 # null descriptor - not used CodeDesc: .word 0xFFFF # limit at maximum: (bits 15:0) .byte 0,0,0 # base at 0: (bits 23:0) .byte 0x9f # present/priv level 0/code/conforming/readable .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) .byte 0 # base at 0: (bits 31:24) DataDesc: .word 0xFFFF # limit at maximum: (bits 15:0) .byte 0,0,0 # base at 0: (bits 23:0) .byte 0x93 # present/priv level 0/data/expand-up/writeable .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) .byte 0 # base at 0: (bits 31:24) /* Global Descriptor Table pointer * contains 6-byte pointer information for LGDT */ GDTptr: .word 0x17 # limit to three 8 byte selectors(null,code,data) .long BIOSRELOC+0x56 # GDT -- arrgh, gas again! /* step 4 relocate to final bootstrap address. */ reloc: movl $ BIOSRELOC,%esi movl $ RELOC,%edi movl $512,%ecx rep movsb movl $0xa0000, %esp pushl $dodisk ret /* step 5 load remaining 15 sectors off disk */ dodisk: movl $ IO_WD1+wd_seccnt,%edx movb $ 15,%al outb %al,%dx NOP movl $ IO_WD1+wd_sector,%edx movb $ 2,%al outb %al,%dx NOP #outb(wdc+wd_cyl_lo, (cyloffset & 0xff)); #outb(wdc+wd_cyl_hi, (cyloffset >> 8)); #outb(wdc+wd_sdh, WDSD_IBM | (unit << 4)); movl $ IO_WD1+wd_command,%edx movb $ WDCC_READ,%al outb %al,%dx NOP cld /* check to make sure controller is not busy and we have data ready */ readblk: movl $ IO_WD1+wd_status,%edx NOP inb %dx,%al testb $ WDCS_BUSY,%al jnz readblk testb $ WDCS_DRQ,%al jz readblk /* read a block into final position in memory */ movl $ IO_WD1+wd_data,%edx movl $ 256,%ecx .byte 0x66,0xf2,0x6d # rep insw NOP /* need more blocks to be read in? */ cmpl $ RELOC+16*512-1,%edi jl readblk /* for clever bootstrap, dig out boot unit and cylinder */ movl $ IO_WD1+wd_cyl_lo,%edx inb %dx,%al xorl %ecx,%ecx movb %al,%cl incl %edx NOP inb %dx,%al /* cyl_hi */ movb %al,%ch pushl %ecx /* cyloffset */ incl %edx xorl %eax,%eax NOP inb %dx,%al /* sdh */ andb $0x10,%al /* isolate unit # bit */ shrb $4,%al pushl %eax /* unit */ /* wd controller is major device 0 */ xorl %eax,%eax pushl %eax /* bootdev */ /* sorry, no flags at this point! */ movl $ start, %eax call %eax /* main (dev, unit, offset) */ ebootblkcode: /* remaining space usable for a disk label */ .org 0x1fe .word 0xaa55 /* signature -- used by BIOS ROM */ ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */