boot1.S revision 40940
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 1640940Srnordier# $Id: boot1.s,v 1.3 1998/10/27 20:19:24 rnordier Exp $ 1740269Srnordier 1840269Srnordier .set MEM_REL,0x600 # Relocation address 1940269Srnordier .set MEM_ARG,0x800 # Arguments 2040269Srnordier .set MEM_PKT,0x810 # Disk packet 2140269Srnordier .set MEM_ORG,0x7c00 # Origin 2240269Srnordier .set MEM_BUF,0x8c00 # Load area 2340269Srnordier .set MEM_BTX,0x9000 # BTX start 2440269Srnordier .set MEM_JMP,0x9010 # BTX entry point 2540269Srnordier .set MEM_USR,0xa000 # Client start 2640269Srnordier 2740269Srnordier .set PRT_OFF,0x1be # Partition offset 2840269Srnordier .set PRT_NUM,0x4 # Partitions 2940269Srnordier .set PRT_BSD,0xa5 # Partition type 3040269Srnordier 3140269Srnordier .set SIZ_PAG,0x1000 # Page size 3240269Srnordier .set SIZ_SEC,0x200 # Sector size 3340269Srnordier 3440269Srnordier .globl start 3540269Srnordier .globl xread 3640269Srnordier 3740269Srnordierstart: jmp main # Start recognizably 3840269Srnordier 3940269Srnordier .org 0x4,0x90 4040269Srnordier 4140269Srnordierxread: pushl %cs # Address 4240269Srnordier popl %ds # data 4340269Srnordierxread.1: movwir(MEM_PKT,_si) # Packet 4440269Srnordier movbr1(_al,0x2,_si_) # Blocks to read 4540269Srnordier o16 # Transfer 4640269Srnordier movwr1(_bx,0x4,_si_) # buffer 4740269Srnordier o16 # LBA 4840269Srnordier movwr1(_cx,0x8,_si_) # address 4940269Srnordier callwi(read) # Read from disk 5040269Srnordier lret # To caller 5140269Srnordier 5240269Srnordiermain: cld # String ops inc 5340269Srnordier xorl %eax,%eax # Zero 5440269Srnordier movl %ax,%es # Address 5540269Srnordier movl %ax,%ds # data 5640269Srnordier movl %ax,%ss # Set up 5740269Srnordier movwir(start,_sp) # stack 5840269Srnordier movl %esp,%esi # Source 5940269Srnordier movwir(MEM_REL,_di) # Destination 6040269Srnordier movwir(0x100,_cx) # Word count 6140269Srnordier rep # Copy 6240269Srnordier movsl # code 6340269Srnordier movb $0x10,%cl # Words to clear 6440269Srnordier rep # Zero 6540269Srnordier stosl # them 6640269Srnordier movbi1(0x10,-0x10,_di_) # Set packet size 6740269Srnordier cmpb $0x80,%dl # Hard drive? 6840269Srnordier jb main.4 # No 6940269Srnordier movwir(part4,_si) # Read master 7040269Srnordier movb $0x1,%al # boot 7140269Srnordier callwi(nread) # record 7240269Srnordier xorl %eax,%eax # Pass number 7340269Srnordiermain.1: movwir(MEM_BUF+PRT_OFF,_si) # Partition table 7440269Srnordier movb $0x1,%dh # Partition 7540269Srnordiermain.2: cmpbi1(PRT_BSD,0x4,_si_) # Our partition type? 7640269Srnordier jne main.3 # No 7740269Srnordier tstbi0(0x80,_si_) # Active? 7840269Srnordier jnz main.5 # Yes 7940269Srnordier testb %al,%al # Second pass? 8040269Srnordier jnz main.5 # Yes 8140269Srnordiermain.3: addl $0x10,%esi # Next entry 8240269Srnordier incb %dh # Partition 8340269Srnordier cmpb $0x1+PRT_NUM,%dh # Done? 8440269Srnordier jb main.2 # No 8540269Srnordier incl %eax # Pass 8640269Srnordier cmpb $0x2,%al # Done? 8740269Srnordier jb main.1 # No 8840269Srnordier movwir(msg_part,_si) # Message 8940269Srnordier jmp error # Error 9040269Srnordiermain.4: xorl %edx,%edx # Partition:drive 9140269Srnordier movwir(part4,_si) # Partition pointer 9240269Srnordiermain.5: movwrm(_dx,MEM_ARG) # Save args 9340269Srnordier movb $0x10,%al # Sector count 9440269Srnordier callwi(nread) # Read disk 9540269Srnordier movwir(MEM_BTX,_bx) # BTX 9640269Srnordier movw1r(0xa,_bx_,_si) # Point past 9740269Srnordier addl %ebx,%esi # it 9840269Srnordier movwir(MEM_USR+SIZ_PAG,_di) # Client page 1 9940314Srnordier movwir(MEM_BTX+0xe*SIZ_SEC,_cx) # Byte 10040269Srnordier subl %esi,%ecx # count 10140269Srnordier rep # Relocate 10240269Srnordier movsb # client 10340269Srnordier subl %edi,%ecx # Byte count 10440269Srnordier xorb %al,%al # Zero 10540269Srnordier rep # assumed 10640269Srnordier stosb # bss 10740269Srnordier callwi(seta20) # Enable A20 10840269Srnordier jmpnwi(start+MEM_JMP-MEM_ORG) # Start BTX 10940269Srnordier 11040269Srnordier# Enable A20 11140269Srnordier 11240675Srnordierseta20: cli # Disable interrupts 11340675Srnordierseta20.1: inb $0x64,%al # Get status 11440269Srnordier testb $0x2,%al # Busy? 11540675Srnordier jnz seta20.1 # Yes 11640269Srnordier movb $0xd1,%al # Command: Write 11740269Srnordier outb %al,$0x64 # output port 11840675Srnordierseta20.2: inb $0x64,%al # Get status 11940269Srnordier testb $0x2,%al # Busy? 12040675Srnordier jnz seta20.2 # Yes 12140269Srnordier movb $0xdf,%al # Enable 12240269Srnordier outb %al,$0x60 # A20 12340675Srnordier sti # Enable interrupts 12440269Srnordier ret # To caller 12540269Srnordier 12640269Srnordier# Read from disk 12740269Srnordier 12840269Srnordiernread: xorw %bx,%bx # Transfer 12940269Srnordier movb $MEM_BUF>>0x8,%bh # buffer 13040269Srnordier o16 # LBA 13140269Srnordier movw1r(0x8,_si_,_cx) # address 13240269Srnordier pushl %cs # Read from 13340269Srnordier callwi(xread.1) # disk 13440269Srnordier jnc return # If success 13540269Srnordier movwir(msg_read,_si) # Message 13640269Srnordier 13740269Srnordier# Error exit 13840269Srnordier 13940269Srnordiererror: callwi(putstr) # Display message 14040269Srnordier movwir(msg_boot,_si) # Display 14140269Srnordier callwi(putstr) # prompt 14240269Srnordier xorb %ah,%ah # BIOS: Get 14340269Srnordier int $0x16 # keypress 14440269Srnordier int $0x19 # BIOS: Reboot 14540269Srnordier 14640269Srnordier# Display string 14740269Srnordier 14840269Srnordierputstr.0: movwir(0x7,_bx) # Page:attribute 14940269Srnordier movb $0xe,%ah # BIOS: Display 15040269Srnordier int $0x10 # character 15140269Srnordierputstr: lodsb # Get char 15240269Srnordier testb %al,%al # End of string? 15340269Srnordier jne putstr.0 # No 15440269Srnordier 15540269Srnordierreturn: ret # Generic return 15640269Srnordier 15740269Srnordier# Read from disk 15840269Srnordier 15940940Srnordierread: tstbim(0x80,MEM_REL+flags-start)# Extensions enabled? 16040269Srnordier jz read.3 # No 16140940Srnordier testb %dh,%dh # Try for extensions? 16240940Srnordier jz read.3 # No 16340269Srnordier movwir(0x55aa,_bx) # Magic 16440269Srnordier pushl %edx # Save 16540269Srnordier movb $0x41,%ah # BIOS: Check 16640269Srnordier int $0x13 # extensions present 16740269Srnordier popl %edx # Restore 16840269Srnordier jc read.3 # If error 16940269Srnordier cmpwir(0xaa55,_bx) # Magic? 17040269Srnordier jne read.3 # No 17140269Srnordier testb $0x1,%cl # Packet interface? 17240269Srnordier jz read.3 # No 17340269Srnordier movb $0x42,%ah # BIOS: Extended 17440269Srnordier int $0x13 # read 17540269Srnordier ret # To caller 17640269Srnordier 17740269Srnordierread.1: movb $0x1,%ah # Invalid 17840269Srnordier stc # parameter 17940269Srnordierread.2: ret # To caller 18040269Srnordier 18140269Srnordierread.3: pushl %edx # Save 18240269Srnordier movb $0x8,%ah # BIOS: Get drive 18340269Srnordier int $0x13 # parameters 18440269Srnordier movb %dh,%ch # Max head number 18540269Srnordier popl %edx # Restore 18640269Srnordier jc read.2 # If error 18740269Srnordier andb $0x3f,%cl # Sectors per track 18840269Srnordier jz read.1 # If zero 18940269Srnordier o16 # Get 19040269Srnordier movw1r(0x8,_si_,_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 19840269Srnordier xorb %dl,%dl # number of 19940269Srnordier divw %bx,%ax # heads 20040269Srnordier movb %dl,%bh # Head number 20140269Srnordier popl %edx # Restore 20240269Srnordier o16 # Cylinder number 20340269Srnordier cmpl $0x3ff,%eax # supportable? 20440269Srnordier ja read.1 # No 20540269Srnordier xchgb %al,%ah # Set up cylinder 20640269Srnordier rorb $0x2,%al # number 20740269Srnordier orb %ch,%al # Merge 20840269Srnordier incl %eax # sector 20940269Srnordier xchgl %eax,%ecx # number 21040269Srnordier movb %bh,%dh # Head number 21140269Srnordier subb %ah,%al # Sectors this track 21240269Srnordier movb1r(0x2,_si_,_ah) # Blocks to read 21340269Srnordier cmpb %ah,%al # To read 21440269Srnordier jb read.4 # this 21540269Srnordier movb %ah,%al # track 21640269Srnordierread.4: movwir(0x5,_bp) # Try count 21740269Srnordierread.5: lesw1r(0x4,_si_,_bx) # Transfer buffer 21840269Srnordier pushl %eax # Save 21940269Srnordier movb $0x2,%ah # BIOS: Conventional 22040269Srnordier int $0x13 # read 22140269Srnordier popl %ebx # Restore 22240269Srnordier jnc read.6 # If success 22340269Srnordier decl %ebp # Retry? 22440269Srnordier jz read.7 # No 22540269Srnordier xorb %ah,%ah # BIOS: Reset 22640269Srnordier int $0x13 # disk system 22740269Srnordier movl %ebx,%eax # Block count 22840269Srnordier jmp read.5 # Continue 22940269Srnordierread.6: movzbw %bl,%ax # Sectors read 23040269Srnordier o16 # Adjust 23140269Srnordier addwr1(_ax,0x8,_si_) # LBA, 23240269Srnordier shlb %bl # buffer 23340269Srnordier addbr1(_bl,0x5,_si_) # pointer, 23440269Srnordier subbr1(_al,0x2,_si_) # block count 23540269Srnordier ja read.3 # If not done 23640269Srnordierread.7: ret # To caller 23740269Srnordier 23840269Srnordier# Messages 23940269Srnordier 24040269Srnordiermsg_read: .asciz "Read error" 24140269Srnordiermsg_part: .asciz "No bootable partition" 24240269Srnordiermsg_boot: .asciz "\r\nHit return to reboot: " 24340269Srnordier 24440940Srnordierflags: .byte FLAGS # Flags 24540940Srnordier 24640269Srnordier .org PRT_OFF,0x90 24740269Srnordier 24840269Srnordier# Partition table 24940269Srnordier 25040269Srnordier .fill 0x30,0x1,0x0 25140269Srnordierpart4: .byte 0x80, 0x00, 0x01, 0x00 25240269Srnordier .byte 0xa5, 0xff, 0xff, 0xff 25340269Srnordier .byte 0x00, 0x00, 0x00, 0x00 25440269Srnordier .byte 0x50, 0xc3, 0x00, 0x00 25540269Srnordier 25640269Srnordier .word 0xaa55 # Magic number 257