148828Swilliam /*- 2*63368Sbostic * Copyright (c) 1990, 1993 3*63368Sbostic * The Regents of the University of California. All rights reserved. 448828Swilliam * 548828Swilliam * This code is derived from software contributed to Berkeley by 648828Swilliam * William Jolitz. 748828Swilliam * 848828Swilliam * %sccs.include.redist.c% 948828Swilliam * 10*63368Sbostic * @(#)wdbootblk.c 8.1 (Berkeley) 06/11/93 1148828Swilliam */ 1248828Swilliam 1348828Swilliam /* 1448828Swilliam * wdbootblk.s: 1548828Swilliam * Written 7/6/90 by William F. Jolitz 1648828Swilliam * Initial block boot for AT/386 with typical Western Digital 1748828Swilliam * WD 1002-WA2 (or upwards compatable). Works either as 1848828Swilliam * first and sole partition bootstrap, or as loaded by a 1948828Swilliam * earlier BIOS boot when on an inner partition of the disk. 2048828Swilliam * 2148828Swilliam * Goal is to read in sucessive 7.5Kbytes of bootstrap to 2248828Swilliam * execute. 2348828Swilliam * 2448828Swilliam * No attempt is made to handle disk errors. 2548828Swilliam */ 2656514Sbostic 2756514Sbostic #include <i386/isa/isa.h> 2856514Sbostic #include <i386/isa/wdreg.h> 2956514Sbostic 3048828Swilliam #define NOP jmp 1f ; nop ; 1: 3148828Swilliam #define BIOSRELOC 0x7c00 3248828Swilliam #define start 0x70400 3348828Swilliam 3448828Swilliam /* step 0 force descriptors to bottom of address space */ 3548828Swilliam 3648828Swilliam .byte 0xfa,0xb8,0x30,0x00,0x8e,0xd0,0xbc,0x00,0x01 #ll fb 3748828Swilliam 3848828Swilliam xorl %eax,%eax 3948828Swilliam movl %ax,%ds 4048828Swilliam movl %ax,%es 4148828Swilliam 4248828Swilliam /* step 1 load new descriptor table */ 4348828Swilliam 4448828Swilliam .byte 0x2E,0x0F,1,0x16 4548828Swilliam .word BIOSRELOC+0x4a #GDTptr 4648828Swilliam # word aword cs lgdt GDTptr 4748828Swilliam 4848828Swilliam /* step 2 turn on protected mode */ 4948828Swilliam 5048828Swilliam smsw %ax 5148828Swilliam orb $1,%al 5248828Swilliam lmsw %ax 5348828Swilliam jmp 1f 5448828Swilliam nop 5548828Swilliam 5648828Swilliam /* step 3 reload segment descriptors */ 5748828Swilliam 5848828Swilliam 1: 5948828Swilliam xorl %eax,%eax 6048828Swilliam movb $0x10,%al 6148828Swilliam movl %ax,%ds 6248828Swilliam movl %ax,%es 6348828Swilliam movl %ax,%ss 6448828Swilliam word 6548828Swilliam ljmp $0x8,$ BIOSRELOC+0x50 /* would be nice if .-RELOC+0x7c00 worked */ 6648828Swilliam 6748828Swilliam /* Global Descriptor Table contains three descriptors: 6848828Swilliam * 0x00: Null: not used 6948828Swilliam * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes 7048828Swilliam * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes 7148828Swilliam * (overlays code) 7248828Swilliam */ 7348828Swilliam GDT: 7448828Swilliam NullDesc: .word 0,0,0,0 # null descriptor - not used 7548828Swilliam CodeDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 7648828Swilliam .byte 0,0,0 # base at 0: (bits 23:0) 7748828Swilliam .byte 0x9f # present/priv level 0/code/conforming/readable 7848828Swilliam .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 7948828Swilliam .byte 0 # base at 0: (bits 31:24) 8048828Swilliam DataDesc: .word 0xFFFF # limit at maximum: (bits 15:0) 8148828Swilliam .byte 0,0,0 # base at 0: (bits 23:0) 8248828Swilliam .byte 0x93 # present/priv level 0/data/expand-up/writeable 8348828Swilliam .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 8448828Swilliam .byte 0 # base at 0: (bits 31:24) 8548828Swilliam 8648828Swilliam /* Global Descriptor Table pointer 8748828Swilliam * contains 6-byte pointer information for LGDT 8848828Swilliam */ 8948828Swilliam GDTptr: .word 0x17 # limit to three 8 byte selectors(null,code,data) 9048828Swilliam .long BIOSRELOC+0x32 # GDT -- arrgh, gas again! 9148828Swilliam 9248828Swilliam /* step 4 relocate to final bootstrap address. */ 9348828Swilliam reloc: 9448828Swilliam movl $ BIOSRELOC,%esi 9548828Swilliam movl $ RELOC,%edi 9648828Swilliam movl $512,%ecx 9748828Swilliam rep 9848828Swilliam movsb 9948828Swilliam movl $0x60000,%esp 10048828Swilliam pushl $dodisk 10148828Swilliam ret 10248828Swilliam 10348828Swilliam /* step 5 load remaining 15 sectors off disk */ 10448828Swilliam dodisk: 10548828Swilliam movl $ IO_WD1+wd_seccnt,%edx 10648828Swilliam movb $ 15,%al 10748828Swilliam outb %al,%dx 10848828Swilliam NOP 10948828Swilliam movl $ IO_WD1+wd_sector,%edx 11048828Swilliam movb $ 2,%al 11148828Swilliam outb %al,%dx 11248828Swilliam NOP 11348828Swilliam #outb(wdc+wd_cyl_lo, (cyloffset & 0xff)); 11448828Swilliam #outb(wdc+wd_cyl_hi, (cyloffset >> 8)); 11548828Swilliam #outb(wdc+wd_sdh, WDSD_IBM | (unit << 4)); 11648828Swilliam 11748828Swilliam movl $ IO_WD1+wd_command,%edx 11848828Swilliam movb $ WDCC_READ,%al 11948828Swilliam outb %al,%dx 12048828Swilliam NOP 12148828Swilliam cld 12248828Swilliam 12348828Swilliam /* check to make sure controller is not busy and we have data ready */ 12448828Swilliam readblk: 12548828Swilliam movl $ IO_WD1+wd_status,%edx 12648828Swilliam inb %dx,%al 12748828Swilliam NOP 12848828Swilliam testb $ WDCS_BUSY,%al 12948828Swilliam jnz readblk 13048828Swilliam testb $ WDCS_DRQ,%al 13148828Swilliam jz readblk 13248828Swilliam 13348828Swilliam /* read a block into final position in memory */ 13448828Swilliam 13548828Swilliam movl $ IO_WD1+wd_data,%edx 13648828Swilliam movl $ 256,%ecx 13748828Swilliam .byte 0x66,0xf2,0x6d # rep insw 13848828Swilliam NOP 13948828Swilliam 14048828Swilliam /* need more blocks to be read in? */ 14148828Swilliam 14248828Swilliam cmpl $ RELOC+16*512-1,%edi 14348828Swilliam jl readblk 14448828Swilliam 14548828Swilliam /* for clever bootstrap, dig out boot unit and cylinder */ 14648828Swilliam 14748828Swilliam movl $ IO_WD1+wd_cyl_lo,%edx 14848828Swilliam inb %dx,%al 14948828Swilliam NOP 15048828Swilliam xorl %ecx,%ecx 15148828Swilliam movb %al,%cl 15248828Swilliam incl %edx 15348828Swilliam inb %dx,%al /* cyl_hi */ 15448828Swilliam NOP 15548828Swilliam movb %al,%ch 15648828Swilliam pushl %ecx /* cyloffset */ 15748828Swilliam 15848828Swilliam incl %edx 15948828Swilliam xorl %eax,%eax 16048828Swilliam inb %dx,%al /* sdh */ 16148828Swilliam andb $0x10,%al /* isolate unit # bit */ 16248828Swilliam shrb $4,%al 16348828Swilliam pushl %eax /* unit */ 16448828Swilliam 16548828Swilliam /* wd controller is major device 0 */ 16648828Swilliam xorl %eax,%eax 16748828Swilliam pushl %eax /* bootdev */ 16848828Swilliam 16948828Swilliam /* sorry, no flags at this point! */ 17048828Swilliam 17148828Swilliam pushl $ start 17248828Swilliam ret /* main (dev, unit, offset) */ 17348828Swilliam 17448828Swilliam ebootblkcode: 17548828Swilliam 17648828Swilliam /* remaining space usable for a disk label */ 17748828Swilliam 17848828Swilliam .space 510-223 /* would be nice if .space 512-2-. worked */ 17948828Swilliam .word 0xaa55 /* signature -- used by BIOS ROM */ 18048828Swilliam 18148828Swilliam ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */ 182