boot1.S revision 40940
1# 2# Copyright (c) 1998 Robert Nordier 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms are freely 6# permitted provided that the above copyright notice and this 7# paragraph and the following disclaimer are duplicated in all 8# such forms. 9# 10# This software is provided "AS IS" and without any express or 11# implied warranties, including, without limitation, the implied 12# warranties of merchantability and fitness for a particular 13# purpose. 14# 15 16# $Id: boot1.s,v 1.3 1998/10/27 20:19:24 rnordier Exp $ 17 18 .set MEM_REL,0x600 # Relocation address 19 .set MEM_ARG,0x800 # Arguments 20 .set MEM_PKT,0x810 # Disk packet 21 .set MEM_ORG,0x7c00 # Origin 22 .set MEM_BUF,0x8c00 # Load area 23 .set MEM_BTX,0x9000 # BTX start 24 .set MEM_JMP,0x9010 # BTX entry point 25 .set MEM_USR,0xa000 # Client start 26 27 .set PRT_OFF,0x1be # Partition offset 28 .set PRT_NUM,0x4 # Partitions 29 .set PRT_BSD,0xa5 # Partition type 30 31 .set SIZ_PAG,0x1000 # Page size 32 .set SIZ_SEC,0x200 # Sector size 33 34 .globl start 35 .globl xread 36 37start: jmp main # Start recognizably 38 39 .org 0x4,0x90 40 41xread: pushl %cs # Address 42 popl %ds # data 43xread.1: movwir(MEM_PKT,_si) # Packet 44 movbr1(_al,0x2,_si_) # Blocks to read 45 o16 # Transfer 46 movwr1(_bx,0x4,_si_) # buffer 47 o16 # LBA 48 movwr1(_cx,0x8,_si_) # address 49 callwi(read) # Read from disk 50 lret # To caller 51 52main: cld # String ops inc 53 xorl %eax,%eax # Zero 54 movl %ax,%es # Address 55 movl %ax,%ds # data 56 movl %ax,%ss # Set up 57 movwir(start,_sp) # stack 58 movl %esp,%esi # Source 59 movwir(MEM_REL,_di) # Destination 60 movwir(0x100,_cx) # Word count 61 rep # Copy 62 movsl # code 63 movb $0x10,%cl # Words to clear 64 rep # Zero 65 stosl # them 66 movbi1(0x10,-0x10,_di_) # Set packet size 67 cmpb $0x80,%dl # Hard drive? 68 jb main.4 # No 69 movwir(part4,_si) # Read master 70 movb $0x1,%al # boot 71 callwi(nread) # record 72 xorl %eax,%eax # Pass number 73main.1: movwir(MEM_BUF+PRT_OFF,_si) # Partition table 74 movb $0x1,%dh # Partition 75main.2: cmpbi1(PRT_BSD,0x4,_si_) # Our partition type? 76 jne main.3 # No 77 tstbi0(0x80,_si_) # Active? 78 jnz main.5 # Yes 79 testb %al,%al # Second pass? 80 jnz main.5 # Yes 81main.3: addl $0x10,%esi # Next entry 82 incb %dh # Partition 83 cmpb $0x1+PRT_NUM,%dh # Done? 84 jb main.2 # No 85 incl %eax # Pass 86 cmpb $0x2,%al # Done? 87 jb main.1 # No 88 movwir(msg_part,_si) # Message 89 jmp error # Error 90main.4: xorl %edx,%edx # Partition:drive 91 movwir(part4,_si) # Partition pointer 92main.5: movwrm(_dx,MEM_ARG) # Save args 93 movb $0x10,%al # Sector count 94 callwi(nread) # Read disk 95 movwir(MEM_BTX,_bx) # BTX 96 movw1r(0xa,_bx_,_si) # Point past 97 addl %ebx,%esi # it 98 movwir(MEM_USR+SIZ_PAG,_di) # Client page 1 99 movwir(MEM_BTX+0xe*SIZ_SEC,_cx) # Byte 100 subl %esi,%ecx # count 101 rep # Relocate 102 movsb # client 103 subl %edi,%ecx # Byte count 104 xorb %al,%al # Zero 105 rep # assumed 106 stosb # bss 107 callwi(seta20) # Enable A20 108 jmpnwi(start+MEM_JMP-MEM_ORG) # Start BTX 109 110# Enable A20 111 112seta20: cli # Disable interrupts 113seta20.1: inb $0x64,%al # Get status 114 testb $0x2,%al # Busy? 115 jnz seta20.1 # Yes 116 movb $0xd1,%al # Command: Write 117 outb %al,$0x64 # output port 118seta20.2: inb $0x64,%al # Get status 119 testb $0x2,%al # Busy? 120 jnz seta20.2 # Yes 121 movb $0xdf,%al # Enable 122 outb %al,$0x60 # A20 123 sti # Enable interrupts 124 ret # To caller 125 126# Read from disk 127 128nread: xorw %bx,%bx # Transfer 129 movb $MEM_BUF>>0x8,%bh # buffer 130 o16 # LBA 131 movw1r(0x8,_si_,_cx) # address 132 pushl %cs # Read from 133 callwi(xread.1) # disk 134 jnc return # If success 135 movwir(msg_read,_si) # Message 136 137# Error exit 138 139error: callwi(putstr) # Display message 140 movwir(msg_boot,_si) # Display 141 callwi(putstr) # prompt 142 xorb %ah,%ah # BIOS: Get 143 int $0x16 # keypress 144 int $0x19 # BIOS: Reboot 145 146# Display string 147 148putstr.0: movwir(0x7,_bx) # Page:attribute 149 movb $0xe,%ah # BIOS: Display 150 int $0x10 # character 151putstr: lodsb # Get char 152 testb %al,%al # End of string? 153 jne putstr.0 # No 154 155return: ret # Generic return 156 157# Read from disk 158 159read: tstbim(0x80,MEM_REL+flags-start)# Extensions enabled? 160 jz read.3 # No 161 testb %dh,%dh # Try for extensions? 162 jz read.3 # No 163 movwir(0x55aa,_bx) # Magic 164 pushl %edx # Save 165 movb $0x41,%ah # BIOS: Check 166 int $0x13 # extensions present 167 popl %edx # Restore 168 jc read.3 # If error 169 cmpwir(0xaa55,_bx) # Magic? 170 jne read.3 # No 171 testb $0x1,%cl # Packet interface? 172 jz read.3 # No 173 movb $0x42,%ah # BIOS: Extended 174 int $0x13 # read 175 ret # To caller 176 177read.1: movb $0x1,%ah # Invalid 178 stc # parameter 179read.2: ret # To caller 180 181read.3: pushl %edx # Save 182 movb $0x8,%ah # BIOS: Get drive 183 int $0x13 # parameters 184 movb %dh,%ch # Max head number 185 popl %edx # Restore 186 jc read.2 # If error 187 andb $0x3f,%cl # Sectors per track 188 jz read.1 # If zero 189 o16 # Get 190 movw1r(0x8,_si_,_ax) # LBA 191 pushl %edx # Save 192 movzbw %cl,%bx # Divide by 193 xorw %dx,%dx # sectors 194 divw %bx,%ax # per track 195 movb %ch,%bl # Max head number 196 movb %dl,%ch # Sector number 197 incl %ebx # Divide by 198 xorb %dl,%dl # number of 199 divw %bx,%ax # heads 200 movb %dl,%bh # Head number 201 popl %edx # Restore 202 o16 # Cylinder number 203 cmpl $0x3ff,%eax # supportable? 204 ja read.1 # No 205 xchgb %al,%ah # Set up cylinder 206 rorb $0x2,%al # number 207 orb %ch,%al # Merge 208 incl %eax # sector 209 xchgl %eax,%ecx # number 210 movb %bh,%dh # Head number 211 subb %ah,%al # Sectors this track 212 movb1r(0x2,_si_,_ah) # Blocks to read 213 cmpb %ah,%al # To read 214 jb read.4 # this 215 movb %ah,%al # track 216read.4: movwir(0x5,_bp) # Try count 217read.5: lesw1r(0x4,_si_,_bx) # Transfer buffer 218 pushl %eax # Save 219 movb $0x2,%ah # BIOS: Conventional 220 int $0x13 # read 221 popl %ebx # Restore 222 jnc read.6 # If success 223 decl %ebp # Retry? 224 jz read.7 # No 225 xorb %ah,%ah # BIOS: Reset 226 int $0x13 # disk system 227 movl %ebx,%eax # Block count 228 jmp read.5 # Continue 229read.6: movzbw %bl,%ax # Sectors read 230 o16 # Adjust 231 addwr1(_ax,0x8,_si_) # LBA, 232 shlb %bl # buffer 233 addbr1(_bl,0x5,_si_) # pointer, 234 subbr1(_al,0x2,_si_) # block count 235 ja read.3 # If not done 236read.7: ret # To caller 237 238# Messages 239 240msg_read: .asciz "Read error" 241msg_part: .asciz "No bootable partition" 242msg_boot: .asciz "\r\nHit return to reboot: " 243 244flags: .byte FLAGS # Flags 245 246 .org PRT_OFF,0x90 247 248# Partition table 249 250 .fill 0x30,0x1,0x0 251part4: .byte 0x80, 0x00, 0x01, 0x00 252 .byte 0xa5, 0xff, 0xff, 0xff 253 .byte 0x00, 0x00, 0x00, 0x00 254 .byte 0x50, 0xc3, 0x00, 0x00 255 256 .word 0xaa55 # Magic number 257