148820Swilliam /*- 2*63368Sbostic * Copyright (c) 1990, 1993 3*63368Sbostic * The Regents of the University of California. All rights reserved. 448820Swilliam * 548820Swilliam * This code is derived from software contributed to Berkeley by 648820Swilliam * William Jolitz. 748820Swilliam * 848820Swilliam * %sccs.include.redist.c% 948820Swilliam * 10*63368Sbostic * @(#)fdbootblk.c 8.1 (Berkeley) 06/11/93 1148820Swilliam */ 1248820Swilliam 1348820Swilliam /* 1452351Sbostic * Initial block boot for AT/386 with typical stupid NEC controller. Works 1552351Sbostic * only with 3.5 inch diskettes that have 16 or greater sectors/side. Goal 1652351Sbostic * is to read in sucessive 7.5Kbytes of bootstrap to execute. No attempt 1752351Sbostic * is made to handle disk errors. 1848820Swilliam */ 1952351Sbostic #define NOP jmp 1f ; nop ; 1: 2052351Sbostic #define BIOSRELOC 0x7c00 2152351Sbostic #define start 0x70400 2248820Swilliam 2352351Sbostic /* Gas does not know about 16 bit opcodes... */ 2452351Sbostic 2548820Swilliam /* step 0 force descriptors to bottom of address space */ 2648820Swilliam 2752351Sbostic .byte 0xfa # cli 2852351Sbostic .byte 0xb8, 0x30, 0x00 # mov $0x0030, %ax 2952351Sbostic .byte 0x8e, 0xd0 # mov %ax, %ss 3052351Sbostic .byte 0xbc, 0x00, 0x01 # mov $0x0100, %sp 3148820Swilliam 3248820Swilliam xorl %eax,%eax 3348820Swilliam movl %ax,%ds 3448820Swilliam movl %ax,%es 3548820Swilliam 3648820Swilliam /* step 1 load new descriptor table */ 3748820Swilliam 3852351Sbostic .byte 0x2e # seg cs 3952351Sbostic .byte 0x0f, 0x01, 0x16 # lgdt DS:d16 4052351Sbostic .word BIOSRELOC + 0x4a # [BIOSRELOC + GDTptr] 4148820Swilliam 4248820Swilliam /* step 2 turn on protected mode */ 4348820Swilliam 4448820Swilliam smsw %ax 4548820Swilliam orb $1,%al 4648820Swilliam lmsw %ax 4748820Swilliam jmp 1f 4848820Swilliam nop 4948820Swilliam 5052351Sbostic 1: 5148820Swilliam /* step 3 reload segment descriptors */ 5248820Swilliam 5348820Swilliam xorl %eax,%eax 5448820Swilliam movb $0x10,%al 5548820Swilliam movl %ax,%ds 5648820Swilliam movl %ax,%es 5748820Swilliam movl %ax,%ss 5848820Swilliam word 5952351Sbostic ljmp $0x8, $ BIOSRELOC + 0x59 # [BIOSRELOC + reloc] 6048820Swilliam 6152351Sbostic /* 6252351Sbostic * Global Descriptor Table contains three descriptors: 6348820Swilliam * 0x00: Null: not used 6448820Swilliam * 0x08: Code: code segment starts at 0 and extents for 4 gigabytes 6548820Swilliam * 0x10: Data: data segment starts at 0 and extends for 4 gigabytes 6648820Swilliam * (overlays code) 6748820Swilliam */ 6848820Swilliam GDT: 6952351Sbostic NullDsc:.word 0,0,0,0 # null descriptor - not used 7052351Sbostic CodeDsc:.word 0xFFFF # limit at maximum: (bits 15:0) 7148820Swilliam .byte 0,0,0 # base at 0: (bits 23:0) 7248820Swilliam .byte 0x9f # present/priv level 0/code/conforming/readable 7348820Swilliam .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 7448820Swilliam .byte 0 # base at 0: (bits 31:24) 7552351Sbostic DataDsc:.word 0xFFFF # limit at maximum: (bits 15:0) 7648820Swilliam .byte 0,0,0 # base at 0: (bits 23:0) 7748820Swilliam .byte 0x93 # present/priv level 0/data/expand-up/writeable 7848820Swilliam .byte 0xcf # page granular/default 32-bit/limit(bits 19:16) 7948820Swilliam .byte 0 # base at 0: (bits 31:24) 8048820Swilliam 8152351Sbostic /* 8252351Sbostic * Global Descriptor Table pointer 8348820Swilliam * contains 6-byte pointer information for LGDT 8448820Swilliam */ 8548820Swilliam GDTptr: .word 0x17 # limit to three 8 byte selectors(null,code,data) 8652351Sbostic .long BIOSRELOC + 0x32 # [BIOSRELOC + GDT] 8748820Swilliam 8852351Sbostic readcmd: .byte 0xe6, 0x00, 0x00, 0x00, 0x00, 0x02, 18, 0x1b, 0xff 8952351Sbostic 9048820Swilliam /* step 4 relocate to final bootstrap address. */ 9148820Swilliam reloc: 9248820Swilliam movl $ BIOSRELOC,%esi 9348820Swilliam movl $ RELOC,%edi 9448820Swilliam movl $512,%ecx 9548820Swilliam rep 9648820Swilliam movsb 9748820Swilliam pushl $dodisk 9848820Swilliam ret 9948820Swilliam 10048820Swilliam /* step 5 load remaining 15 sectors off disk */ 10148820Swilliam dodisk: 10248820Swilliam movl $0x70200,%edi 10348820Swilliam xorl %ebx,%ebx 10448820Swilliam incb %bl 10548820Swilliam incb %bl 10648820Swilliam movb $0x20,%al # do a eoi 10748820Swilliam outb %al,$0x20 10848820Swilliam 10948820Swilliam NOP 11048820Swilliam movb $0x07,%al 11148820Swilliam outb %al,$0x21 11248820Swilliam NOP 11348820Swilliam 8: 11448820Swilliam movb %bl,readcmd+4 11548820Swilliam movl %edi,%ecx 11648820Swilliam 11748820Swilliam /* Set read/write bytes */ 11848820Swilliam xorl %edx,%edx 11948820Swilliam movb $0x0c,%dl # outb(0xC,0x46); outb(0xB,0x46); 12048820Swilliam movb $0x46,%al 12148820Swilliam outb %al,%dx 12248820Swilliam NOP 12348820Swilliam decb %dx 12448820Swilliam outb %al,%dx 12548820Swilliam 12648820Swilliam /* Send start address */ 12748820Swilliam movb $0x04,%dl # outb(0x4, addr); 12848820Swilliam movb %cl,%al 12948820Swilliam outb %al,%dx 13048820Swilliam NOP 13148820Swilliam movb %ch,%al # outb(0x4, addr>>8); 13248820Swilliam outb %al,%dx 13348820Swilliam NOP 13448820Swilliam rorl $8,%ecx # outb(0x81, addr>>16); 13548820Swilliam movb %ch,%al 13648820Swilliam outb %al,$0x81 13748820Swilliam NOP 13848820Swilliam 13948820Swilliam /* Send count */ 14048820Swilliam movb $0x05,%dl # outb(0x5, 0); 14148820Swilliam xorl %eax,%eax 14248820Swilliam outb %al,%dx 14348820Swilliam NOP 14448820Swilliam movb $2,%al # outb(0x5,2); 14548820Swilliam outb %al,%dx 14648820Swilliam NOP 14748820Swilliam 14848820Swilliam /* set channel 2 */ 14948820Swilliam # movb $2,%al # outb(0x0A,2); 15048820Swilliam outb %al,$0x0A 15148820Swilliam NOP 15248820Swilliam 15348820Swilliam /* issue read command to fdc */ 15448820Swilliam movw $0x3f4,%dx 15548820Swilliam movl $readcmd,%esi 15648820Swilliam xorl %ecx,%ecx 15748820Swilliam movb $9,%cl 15848820Swilliam 15948820Swilliam 2: inb %dx,%al 16048820Swilliam NOP 16148820Swilliam testb $0x80,%al 16248820Swilliam jz 2b 16348820Swilliam 16448820Swilliam incb %dx 16548820Swilliam movl (%esi),%al 16648820Swilliam outb %al,%dx 16748820Swilliam NOP 16848820Swilliam incl %esi 16948820Swilliam decb %dx 17048820Swilliam loop 2b 17148820Swilliam 17248820Swilliam /* watch the icu looking for an interrupt signalling completion */ 17348820Swilliam xorl %edx,%edx 17448820Swilliam movb $0x20,%dl 17548820Swilliam 2: movb $0xc,%al 17648820Swilliam outb %al,%dx 17748820Swilliam NOP 17848820Swilliam inb %dx,%al 17948820Swilliam NOP 18048820Swilliam andb $0x7f,%al 18148820Swilliam cmpb $6,%al 18248820Swilliam jne 2b 18348820Swilliam movb $0x20,%al # do a eoi 18448820Swilliam outb %al,%dx 18548820Swilliam NOP 18648820Swilliam 18748820Swilliam movl $0x3f4,%edx 18848820Swilliam xorl %ecx,%ecx 18948820Swilliam movb $7,%cl 19048820Swilliam 2: inb %dx,%al 19148820Swilliam NOP 19248820Swilliam andb $0xC0,%al 19348820Swilliam cmpb $0xc0,%al 19448820Swilliam jne 2b 19548820Swilliam incb %dx 19648820Swilliam inb %dx,%al 19748820Swilliam decb %dx 19848820Swilliam loop 2b 19948820Swilliam 20048820Swilliam /* extract the status bytes after the read. must we do this? */ 20148820Swilliam addw $0x200,%edi # next addr to load to 20248820Swilliam incb %bl 20348820Swilliam cmpb $16,%bl 20448820Swilliam jle 8b 20548820Swilliam 20648820Swilliam /* for clever bootstrap, dig out boot unit and cylinder */ 20748820Swilliam pushl $0 20848820Swilliam pushl $0 20948820Swilliam 21048820Swilliam /* fd controller is major device 2 */ 21148820Swilliam pushl $2 /* dev */ 21248820Swilliam 21348820Swilliam /* sorry, no flags at this point! */ 21448820Swilliam 21548820Swilliam pushl $ start 21648820Swilliam ret /* main (dev, unit, off) */ 21748820Swilliam 21848820Swilliam ebootblkcode: 21948820Swilliam 22048820Swilliam /* remaining space usable for a disk label */ 22148820Swilliam 22248820Swilliam .space 510-310 /* would be nice if .space 512-2-. worked */ 22348820Swilliam .word 0xaa55 /* signature -- used by BIOS ROM */ 22448820Swilliam 22548820Swilliam ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */ 226