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