boot1.S revision 48919
140269Srnordier# 240269Srnordier# Copyright (c) 1998 Robert Nordier 340269Srnordier# All rights reserved. 440269Srnordier# 540269Srnordier# Redistribution and use in source and binary forms are freely 640269Srnordier# permitted provided that the above copyright notice and this 740269Srnordier# paragraph and the following disclaimer are duplicated in all 840269Srnordier# such forms. 940269Srnordier# 1040269Srnordier# This software is provided "AS IS" and without any express or 1140269Srnordier# implied warranties, including, without limitation, the implied 1240269Srnordier# warranties of merchantability and fitness for a particular 1340269Srnordier# purpose. 1440269Srnordier# 1540269Srnordier 1648919Srnordier# $Id: boot1.s,v 1.8 1999/01/13 23:30:07 rnordier Exp $ 1740269Srnordier 1842478Speter .set MEM_REL,0x700 # Relocation address 1942478Speter .set MEM_ARG,0x900 # Arguments 2040269Srnordier .set MEM_ORG,0x7c00 # Origin 2140269Srnordier .set MEM_BUF,0x8c00 # Load area 2240269Srnordier .set MEM_BTX,0x9000 # BTX start 2340269Srnordier .set MEM_JMP,0x9010 # BTX entry point 2440269Srnordier .set MEM_USR,0xa000 # Client start 2540269Srnordier 2640269Srnordier .set PRT_OFF,0x1be # Partition offset 2740269Srnordier .set PRT_NUM,0x4 # Partitions 2840269Srnordier .set PRT_BSD,0xa5 # Partition type 2940269Srnordier 3040269Srnordier .set SIZ_PAG,0x1000 # Page size 3140269Srnordier .set SIZ_SEC,0x200 # Sector size 3240269Srnordier 3340269Srnordier .globl start 3440269Srnordier .globl xread 3540269Srnordier 3640269Srnordierstart: jmp main # Start recognizably 3740269Srnordier 3840269Srnordier .org 0x4,0x90 3940269Srnordier 4041008Srnordier# External read from disk 4141008Srnordier 4248919Srnordierxread: pushl %ss # Address 4348919Srnordier popl %ds # data 4448919Srnordierxread.1: o16 # Starting 4548919Srnordier pushb $0x0 # absolute 4648919Srnordier pushl %ecx # block 4748919Srnordier pushl %eax # number 4848919Srnordier pushl %es # Address of 4948919Srnordier pushl %ebx # transfer buffer 5048919Srnordier xorl %eax,%eax # Number of 5148919Srnordier movb %dh,%al # blocks to 5248919Srnordier pushl %eax # transfer 5348919Srnordier pushb $0x10 # Size of packet 5448919Srnordier movl %esp,%ebp # Packet pointer 5540269Srnordier callwi(read) # Read from disk 5648919Srnordier leaw1r(0x10,_bp_,_sp) # Clear stack 5741008Srnordier lret # To far caller 5840269Srnordier 5941008Srnordier# Bootstrap 6041008Srnordier 6140269Srnordiermain: cld # String ops inc 6241008Srnordier xorl %ecx,%ecx # Zero 6341008Srnordier movl %cx,%es # Address 6441008Srnordier movl %cx,%ds # data 6541008Srnordier movl %cx,%ss # Set up 6640269Srnordier movwir(start,_sp) # stack 6740269Srnordier movl %esp,%esi # Source 6840269Srnordier movwir(MEM_REL,_di) # Destination 6941008Srnordier incb %ch # Word count 7040269Srnordier rep # Copy 7140269Srnordier movsl # code 7241008Srnordier movwir(part4,_si) # Partition 7340269Srnordier cmpb $0x80,%dl # Hard drive? 7440269Srnordier jb main.4 # No 7541008Srnordier movb $0x1,%dh # Block count 7641008Srnordier callwi(nread) # Read MBR 7741008Srnordier movwir(0x1,_cx) # Two passes 7840269Srnordiermain.1: movwir(MEM_BUF+PRT_OFF,_si) # Partition table 7940269Srnordier movb $0x1,%dh # Partition 8040269Srnordiermain.2: cmpbi1(PRT_BSD,0x4,_si_) # Our partition type? 8140269Srnordier jne main.3 # No 8241008Srnordier jecxz main.5 # If second pass 8340269Srnordier tstbi0(0x80,_si_) # Active? 8440269Srnordier jnz main.5 # Yes 8540269Srnordiermain.3: addl $0x10,%esi # Next entry 8640269Srnordier incb %dh # Partition 8741008Srnordier cmpb $0x1+PRT_NUM,%dh # In table? 8841008Srnordier jb main.2 # Yes 8941008Srnordier decl %ecx # Do two 9041008Srnordier jecxz main.1 # passes 9140269Srnordier movwir(msg_part,_si) # Message 9240269Srnordier jmp error # Error 9340269Srnordiermain.4: xorl %edx,%edx # Partition:drive 9440269Srnordiermain.5: movwrm(_dx,MEM_ARG) # Save args 9541008Srnordier movb $0x10,%dh # Sector count 9640269Srnordier callwi(nread) # Read disk 9740269Srnordier movwir(MEM_BTX,_bx) # BTX 9840269Srnordier movw1r(0xa,_bx_,_si) # Point past 9940269Srnordier addl %ebx,%esi # it 10040269Srnordier movwir(MEM_USR+SIZ_PAG,_di) # Client page 1 10140314Srnordier movwir(MEM_BTX+0xe*SIZ_SEC,_cx) # Byte 10240269Srnordier subl %esi,%ecx # count 10340269Srnordier rep # Relocate 10440269Srnordier movsb # client 10540269Srnordier subl %edi,%ecx # Byte count 10640269Srnordier xorb %al,%al # Zero 10740269Srnordier rep # assumed 10840269Srnordier stosb # bss 10940269Srnordier callwi(seta20) # Enable A20 11040269Srnordier jmpnwi(start+MEM_JMP-MEM_ORG) # Start BTX 11140269Srnordier 11240269Srnordier# Enable A20 11340269Srnordier 11440675Srnordierseta20: cli # Disable interrupts 11540675Srnordierseta20.1: inb $0x64,%al # Get status 11640269Srnordier testb $0x2,%al # Busy? 11740675Srnordier jnz seta20.1 # Yes 11840269Srnordier movb $0xd1,%al # Command: Write 11940269Srnordier outb %al,$0x64 # output port 12040675Srnordierseta20.2: inb $0x64,%al # Get status 12140269Srnordier testb $0x2,%al # Busy? 12240675Srnordier jnz seta20.2 # Yes 12340269Srnordier movb $0xdf,%al # Enable 12440269Srnordier outb %al,$0x60 # A20 12540675Srnordier sti # Enable interrupts 12640269Srnordier ret # To caller 12740269Srnordier 12841008Srnordier# Local read from disk 12940269Srnordier 13041008Srnordiernread: movwir(MEM_BUF,_bx) # Transfer buffer 13141008Srnordier movw1r(0x8,_si_,_ax) # Get 13241008Srnordier movw1r(0xa,_si_,_cx) # LBA 13340269Srnordier pushl %cs # Read from 13448919Srnordier callwi(xread.1) # disk 13540269Srnordier jnc return # If success 13640269Srnordier movwir(msg_read,_si) # Message 13740269Srnordier 13840269Srnordier# Error exit 13940269Srnordier 14040269Srnordiererror: callwi(putstr) # Display message 14141008Srnordier movwir(prompt,_si) # Display 14240269Srnordier callwi(putstr) # prompt 14340269Srnordier xorb %ah,%ah # BIOS: Get 14440269Srnordier int $0x16 # keypress 14540269Srnordier int $0x19 # BIOS: Reboot 14640269Srnordier 14740269Srnordier# Display string 14840269Srnordier 14940269Srnordierputstr.0: movwir(0x7,_bx) # Page:attribute 15040269Srnordier movb $0xe,%ah # BIOS: Display 15140269Srnordier int $0x10 # character 15240269Srnordierputstr: lodsb # Get char 15340269Srnordier testb %al,%al # End of string? 15440269Srnordier jne putstr.0 # No 15540269Srnordier 15641008Srnordierereturn: movb $0x1,%ah # Invalid 15741008Srnordier stc # argument 15841008Srnordierreturn: ret # To caller 15940269Srnordier 16040269Srnordier# Read from disk 16140269Srnordier 16248919Srnordierread: cs_ # LBA support 16348919Srnordier tstbim(0x80,MEM_REL+flags-start)# enabled? 16448919Srnordier jz read.1 # No 16548919Srnordier movwir(0x55aa,_bx) # Magic 16640269Srnordier pushl %edx # Save 16748919Srnordier movb $0x41,%ah # BIOS: Check 16848919Srnordier int $0x13 # extensions present 16948919Srnordier popl %edx # Restore 17048919Srnordier jc read.1 # If error 17148919Srnordier cmpwir(0xaa55,_bx) # Magic? 17248919Srnordier jne read.1 # No 17348919Srnordier testb $0x1,%cl # Packet interface? 17448919Srnordier jz read.1 # No 17548919Srnordier movl %ebp,%esi # Disk packet 17648919Srnordier movb $0x42,%ah # BIOS: Extended 17748919Srnordier int $0x13 # read 17848919Srnordier ret # To caller 17948919Srnordier 18048919Srnordierread.1: pushl %edx # Save 18140269Srnordier movb $0x8,%ah # BIOS: Get drive 18240269Srnordier int $0x13 # parameters 18340269Srnordier movb %dh,%ch # Max head number 18440269Srnordier popl %edx # Restore 18541008Srnordier jc return # If error 18640269Srnordier andb $0x3f,%cl # Sectors per track 18741008Srnordier jz ereturn # If zero 18841008Srnordier cli # Disable interrupts 18940269Srnordier o16 # Get 19041008Srnordier movw1r(0x8,_bp_,_ax) # LBA 19140269Srnordier pushl %edx # Save 19240269Srnordier movzbw %cl,%bx # Divide by 19340269Srnordier xorw %dx,%dx # sectors 19440269Srnordier divw %bx,%ax # per track 19540269Srnordier movb %ch,%bl # Max head number 19640269Srnordier movb %dl,%ch # Sector number 19740269Srnordier incl %ebx # Divide by 19841008Srnordier xorb %dl,%dl # number 19941008Srnordier divw %bx,%ax # of heads 20040269Srnordier movb %dl,%bh # Head number 20140269Srnordier popl %edx # Restore 20240269Srnordier o16 # Cylinder number 20340269Srnordier cmpl $0x3ff,%eax # supportable? 20441008Srnordier sti # Enable interrupts 20541008Srnordier ja ereturn # No 20640269Srnordier xchgb %al,%ah # Set up cylinder 20740269Srnordier rorb $0x2,%al # number 20840269Srnordier orb %ch,%al # Merge 20940269Srnordier incl %eax # sector 21040269Srnordier xchgl %eax,%ecx # number 21140269Srnordier movb %bh,%dh # Head number 21240269Srnordier subb %ah,%al # Sectors this track 21348919Srnordier movb1r(0x2,_bp_,_ah) # Blocks to read 21440269Srnordier cmpb %ah,%al # To read 21548919Srnordier jb read.2 # this 21640269Srnordier movb %ah,%al # track 21748919Srnordierread.2: movwir(0x5,_di) # Try count 21848919Srnordierread.3: lesw1r(0x4,_bp_,_bx) # Transfer buffer 21940269Srnordier pushl %eax # Save 22041008Srnordier movb $0x2,%ah # BIOS: Read 22141008Srnordier int $0x13 # from disk 22240269Srnordier popl %ebx # Restore 22348919Srnordier jnc read.4 # If success 22441008Srnordier decl %edi # Retry? 22548919Srnordier jz read.6 # No 22640269Srnordier xorb %ah,%ah # BIOS: Reset 22740269Srnordier int $0x13 # disk system 22841008Srnordier xchgl %ebx,%eax # Block count 22948919Srnordier jmp read.3 # Continue 23048919Srnordierread.4: movzbl %bl,%eax # Sectors read 23141008Srnordier addwr1(_ax,0x8,_bp_) # Adjust 23248919Srnordier jnc read.5 # LBA, 23341008Srnordier incw1(0xa,_bp_) # transfer 23448919Srnordierread.5: shlb %bl # buffer 23541008Srnordier addbr1(_bl,0x5,_bp_) # pointer, 23648919Srnordier subbr1(_al,0x2,_bp_) # block count 23748919Srnordier ja read.1 # If not done 23848919Srnordierread.6: ret # To caller 23940269Srnordier 24040269Srnordier# Messages 24140269Srnordier 24241008Srnordiermsg_read: .asciz "Read" 24341008Srnordiermsg_part: .asciz "Boot" 24440269Srnordier 24541085Srnordierprompt: .asciz " error\r\n" 24640940Srnordier 24748919Srnordierflags: .byte FLAGS # Flags 24848919Srnordier 24940269Srnordier .org PRT_OFF,0x90 25040269Srnordier 25140269Srnordier# Partition table 25240269Srnordier 25340269Srnordier .fill 0x30,0x1,0x0 25440269Srnordierpart4: .byte 0x80, 0x00, 0x01, 0x00 25540269Srnordier .byte 0xa5, 0xff, 0xff, 0xff 25640269Srnordier .byte 0x00, 0x00, 0x00, 0x00 25740269Srnordier .byte 0x50, 0xc3, 0x00, 0x00 25840269Srnordier 25940269Srnordier .word 0xaa55 # Magic number 260