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