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