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