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 * @(#)fdbootblk.c 7.1 (Berkeley) 04/28/91 11 */ 12 13 /* 14 * fdbootblk.s: 15 * Written 10/6/90 by William F. Jolitz 16 * Initial block boot for AT/386 with typical stupid NEC controller 17 * Works only with 3.5 inch diskettes that have 16 or greater sectors/side 18 * 19 * Goal is to read in sucessive 7.5Kbytes of bootstrap to 20 * execute. 21 * 22 * No attempt is made to handle disk errors. 23 */ 24 /*#include "/sys/i386/isa/isa.h" 25 #include "/sys/i386/isa/fdreg.h"*/ 26 #define NOP jmp 1f ; nop ; 1: 27 #define BIOSRELOC 0x7c00 28 #define start 0x70400 29 30 /* step 0 force descriptors to bottom of address space */ 31 32 .byte 0xfa,0xb8,0x30,0x00,0x8e,0xd0,0xbc,0x00,0x01 #ll fb 33 34 xorl %eax,%eax 35 movl %ax,%ds 36 movl %ax,%es 37 38 /* step 1 load new descriptor table */ 39 40 .byte 0x2E,0x0F,1,0x16 41 .word BIOSRELOC+0x4a #GDTptr 42 # word aword cs lgdt GDTptr 43 44 /* step 2 turn on protected mode */ 45 46 smsw %ax 47 orb $1,%al 48 lmsw %ax 49 jmp 1f 50 nop 51 52 /* step 3 reload segment descriptors */ 53 54 1: 55 xorl %eax,%eax 56 movb $0x10,%al 57 movl %ax,%ds 58 movl %ax,%es 59 movl %ax,%ss 60 word 61 ljmp $0x8,$ BIOSRELOC+0x59 /* would be nice if .-RELOC+0x7c00 worked */ 62 63 /* Global Descriptor Table contains three descriptors: 64 * 0x00: Null: not used 65 * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes 66 * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes 67 * (overlays code) 68 */ 69 GDT: 70 NullDesc: .word 0,0,0,0 # null descriptor - not used 71 CodeDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 72 .byte 0,0,0 # base at 0: (bits 23:0) 73 .byte 0x9f # present/priv level 0/code/conforming/readable 74 .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 75 .byte 0 # base at 0: (bits 31:24) 76 DataDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 77 .byte 0,0,0 # base at 0: (bits 23:0) 78 .byte 0x93 # present/priv level 0/data/expand-up/writeable 79 .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 80 .byte 0 # base at 0: (bits 31:24) 81 82 /* Global Descriptor Table pointer 83 * contains 6-byte pointer information for LGDT 84 */ 85 GDTptr: .word 0x17 # limit to three 8 byte selectors(null,code,data) 86 .long BIOSRELOC+0x32 # GDT -- arrgh, gas again! 87 readcmd: .byte 0xe6,0,0,0,0,2,18,0x1b,0xff 88 89 /* step 4 relocate to final bootstrap address. */ 90 reloc: 91 movl $ BIOSRELOC,%esi 92 movl $ RELOC,%edi 93 movl $512,%ecx 94 rep 95 movsb 96 pushl $dodisk 97 ret 98 99 /* step 5 load remaining 15 sectors off disk */ 100 dodisk: 101 movl $0x70200,%edi 102 xorl %ebx,%ebx 103 incb %bl 104 incb %bl 105 #ifdef notdef 106 movb $0x11,%al 107 outb %al,$0x20 108 NOP 109 movb $32,%al 110 outb %al,$0x21 111 NOP 112 movb $4,%al 113 outb %al,$0x21 114 NOP 115 movb $1,%al 116 outb %al,$0x21 117 NOP 118 #endif 119 movb $0x20,%al # do a eoi 120 outb %al,$0x20 121 122 NOP 123 movb $0x07,%al 124 outb %al,$0x21 125 NOP 126 8: 127 movb %bl,readcmd+4 128 movl %edi,%ecx 129 130 /* Set read/write bytes */ 131 xorl %edx,%edx 132 movb $0x0c,%dl # outb(0xC,0x46); outb(0xB,0x46); 133 movb $0x46,%al 134 outb %al,%dx 135 NOP 136 decb %dx 137 outb %al,%dx 138 139 /* Send start address */ 140 movb $0x04,%dl # outb(0x4, addr); 141 movb %cl,%al 142 outb %al,%dx 143 NOP 144 movb %ch,%al # outb(0x4, addr>>8); 145 outb %al,%dx 146 NOP 147 rorl $8,%ecx # outb(0x81, addr>>16); 148 movb %ch,%al 149 outb %al,$0x81 150 NOP 151 152 /* Send count */ 153 movb $0x05,%dl # outb(0x5, 0); 154 xorl %eax,%eax 155 outb %al,%dx 156 NOP 157 movb $2,%al # outb(0x5,2); 158 outb %al,%dx 159 NOP 160 161 /* set channel 2 */ 162 # movb $2,%al # outb(0x0A,2); 163 outb %al,$0x0A 164 NOP 165 166 /* issue read command to fdc */ 167 movw $0x3f4,%dx 168 movl $readcmd,%esi 169 xorl %ecx,%ecx 170 movb $9,%cl 171 172 2: inb %dx,%al 173 NOP 174 testb $0x80,%al 175 jz 2b 176 177 incb %dx 178 movl (%esi),%al 179 outb %al,%dx 180 NOP 181 incl %esi 182 decb %dx 183 loop 2b 184 185 /* watch the icu looking for an interrupt signalling completion */ 186 xorl %edx,%edx 187 movb $0x20,%dl 188 2: movb $0xc,%al 189 outb %al,%dx 190 NOP 191 inb %dx,%al 192 NOP 193 #ifdef notdef 194 call px 195 #endif 196 andb $0x7f,%al 197 cmpb $6,%al 198 jne 2b 199 movb $0x20,%al # do a eoi 200 outb %al,%dx 201 NOP 202 203 movl $0x3f4,%edx 204 xorl %ecx,%ecx 205 movb $7,%cl 206 2: inb %dx,%al 207 NOP 208 andb $0xC0,%al 209 cmpb $0xc0,%al 210 jne 2b 211 incb %dx 212 inb %dx,%al 213 decb %dx 214 loop 2b 215 216 #ifdef notdef 217 inb $0x61,%al 218 NOP 219 orb $3,%al 220 outb %al,$0x61 221 NOP 222 #endif 223 224 /* extract the status bytes after the read. must we do this? */ 225 addw $0x200,%edi # next addr to load to 226 incb %bl 227 #ifdef notdef 228 movb %bl,%al 229 call px 230 #endif 231 cmpb $16,%bl 232 jle 8b 233 234 /* for clever bootstrap, dig out boot unit and cylinder */ 235 pushl $0 236 pushl $0 237 238 /* fd controller is major device 2 */ 239 pushl $2 /* dev */ 240 241 /* sorry, no flags at this point! */ 242 243 pushl $ start 244 ret /* main (dev, unit, off) */ 245 246 #ifdef notdef 247 hextab: .ascii "0123456789abcdef" 248 curs: .long 0xb8000 249 kbc: .byte 0 250 251 px: 252 pushal 253 movl curs,%edi 254 movl %eax,%ebx 255 call phd 256 movl %ebx,%eax 257 shrl $4,%eax 258 call phd 259 movb $0xe,%ah 260 movb $32,%al 261 movw %ax,(%edi) 262 # movw $(0xe<<8)+' ',(%edi) 263 incl %edi 264 incl %edi 265 movl %edi,curs 266 267 2: inb $0x60,%al 268 NOP 269 cmpb %al,kbc 270 je 2b 271 movb %al,kbc 272 273 popal 274 ret 275 276 phd: 277 andl $0xf,%eax 278 movb hextab(%eax),%al 279 movb $0xe,%ah 280 movw %ax,(%edi) 281 incl %edi 282 incl %edi 283 ret 284 #endif 285 286 ebootblkcode: 287 288 /* remaining space usable for a disk label */ 289 290 .space 510-310 /* would be nice if .space 512-2-. worked */ 291 .word 0xaa55 /* signature -- used by BIOS ROM */ 292 293 ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */ 294