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