1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)wdbootblk.c 8.1 (Berkeley) 06/11/93 11 */ 12 13 /* 14 * wdbootblk.s: 15 * Written 7/6/90 by William F. Jolitz 16 * Initial block boot for AT/386 with typical Western Digital 17 * WD 1002-WA2 (or upwards compatable). Works either as 18 * first and sole partition bootstrap, or as loaded by a 19 * earlier BIOS boot when on an inner partition of the disk. 20 * 21 * Goal is to read in sucessive 7.5Kbytes of bootstrap to 22 * execute. 23 * 24 * No attempt is made to handle disk errors. 25 */ 26 27 #include <i386/isa/isa.h> 28 #include <i386/isa/wdreg.h> 29 30 #define NOP jmp 1f ; nop ; 1: 31 #define BIOSRELOC 0x7c00 32 #define start 0x70400 33 34 /* step 0 force descriptors to bottom of address space */ 35 36 .byte 0xfa,0xb8,0x30,0x00,0x8e,0xd0,0xbc,0x00,0x01 #ll fb 37 38 xorl %eax,%eax 39 movl %ax,%ds 40 movl %ax,%es 41 42 /* step 1 load new descriptor table */ 43 44 .byte 0x2E,0x0F,1,0x16 45 .word BIOSRELOC+0x4a #GDTptr 46 # word aword cs lgdt GDTptr 47 48 /* step 2 turn on protected mode */ 49 50 smsw %ax 51 orb $1,%al 52 lmsw %ax 53 jmp 1f 54 nop 55 56 /* step 3 reload segment descriptors */ 57 58 1: 59 xorl %eax,%eax 60 movb $0x10,%al 61 movl %ax,%ds 62 movl %ax,%es 63 movl %ax,%ss 64 word 65 ljmp $0x8,$ BIOSRELOC+0x50 /* would be nice if .-RELOC+0x7c00 worked */ 66 67 /* Global Descriptor Table contains three descriptors: 68 * 0x00: Null: not used 69 * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes 70 * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes 71 * (overlays code) 72 */ 73 GDT: 74 NullDesc: .word 0,0,0,0 # null descriptor - not used 75 CodeDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 76 .byte 0,0,0 # base at 0: (bits 23:0) 77 .byte 0x9f # present/priv level 0/code/conforming/readable 78 .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 79 .byte 0 # base at 0: (bits 31:24) 80 DataDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 81 .byte 0,0,0 # base at 0: (bits 23:0) 82 .byte 0x93 # present/priv level 0/data/expand-up/writeable 83 .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 84 .byte 0 # base at 0: (bits 31:24) 85 86 /* Global Descriptor Table pointer 87 * contains 6-byte pointer information for LGDT 88 */ 89 GDTptr: .word 0x17 # limit to three 8 byte selectors(null,code,data) 90 .long BIOSRELOC+0x32 # GDT -- arrgh, gas again! 91 92 /* step 4 relocate to final bootstrap address. */ 93 reloc: 94 movl $ BIOSRELOC,%esi 95 movl $ RELOC,%edi 96 movl $512,%ecx 97 rep 98 movsb 99 movl $0x60000,%esp 100 pushl $dodisk 101 ret 102 103 /* step 5 load remaining 15 sectors off disk */ 104 dodisk: 105 movl $ IO_WD1+wd_seccnt,%edx 106 movb $ 15,%al 107 outb %al,%dx 108 NOP 109 movl $ IO_WD1+wd_sector,%edx 110 movb $ 2,%al 111 outb %al,%dx 112 NOP 113 #outb(wdc+wd_cyl_lo, (cyloffset & 0xff)); 114 #outb(wdc+wd_cyl_hi, (cyloffset >> 8)); 115 #outb(wdc+wd_sdh, WDSD_IBM | (unit << 4)); 116 117 movl $ IO_WD1+wd_command,%edx 118 movb $ WDCC_READ,%al 119 outb %al,%dx 120 NOP 121 cld 122 123 /* check to make sure controller is not busy and we have data ready */ 124 readblk: 125 movl $ IO_WD1+wd_status,%edx 126 inb %dx,%al 127 NOP 128 testb $ WDCS_BUSY,%al 129 jnz readblk 130 testb $ WDCS_DRQ,%al 131 jz readblk 132 133 /* read a block into final position in memory */ 134 135 movl $ IO_WD1+wd_data,%edx 136 movl $ 256,%ecx 137 .byte 0x66,0xf2,0x6d # rep insw 138 NOP 139 140 /* need more blocks to be read in? */ 141 142 cmpl $ RELOC+16*512-1,%edi 143 jl readblk 144 145 /* for clever bootstrap, dig out boot unit and cylinder */ 146 147 movl $ IO_WD1+wd_cyl_lo,%edx 148 inb %dx,%al 149 NOP 150 xorl %ecx,%ecx 151 movb %al,%cl 152 incl %edx 153 inb %dx,%al /* cyl_hi */ 154 NOP 155 movb %al,%ch 156 pushl %ecx /* cyloffset */ 157 158 incl %edx 159 xorl %eax,%eax 160 inb %dx,%al /* sdh */ 161 andb $0x10,%al /* isolate unit # bit */ 162 shrb $4,%al 163 pushl %eax /* unit */ 164 165 /* wd controller is major device 0 */ 166 xorl %eax,%eax 167 pushl %eax /* bootdev */ 168 169 /* sorry, no flags at this point! */ 170 171 pushl $ start 172 ret /* main (dev, unit, offset) */ 173 174 ebootblkcode: 175 176 /* remaining space usable for a disk label */ 177 178 .space 510-223 /* would be nice if .space 512-2-. worked */ 179 .word 0xaa55 /* signature -- used by BIOS ROM */ 180 181 ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */ 182