boot1.S revision 50477
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# $FreeBSD: head/sys/boot/i386/boot2/boot1.S 50477 1999-08-28 01:08:13Z peter $
17
18		.set MEM_REL,0x700		# Relocation address
19		.set MEM_ARG,0x900		# Arguments
20		.set MEM_ORG,0x7c00		# Origin
21		.set MEM_BUF,0x8c00		# Load area
22		.set MEM_BTX,0x9000		# BTX start
23		.set MEM_JMP,0x9010		# BTX entry point
24		.set MEM_USR,0xa000		# Client start
25
26		.set PRT_OFF,0x1be		# Partition offset
27		.set PRT_NUM,0x4		# Partitions
28		.set PRT_BSD,0xa5		# Partition type
29
30		.set SIZ_PAG,0x1000		# Page size
31		.set SIZ_SEC,0x200		# Sector size
32
33		.globl start
34		.globl xread
35
36start:		jmp main			# Start recognizably
37
38		.org 0x4,0x90
39
40# External read from disk
41
42xread:		pushl %ss			# Address
43		popl %ds			#  data
44xread.1:	o16				# Starting
45		pushb $0x0			#  absolute
46		pushl %ecx			#  block
47		pushl %eax			#  number
48		pushl %es			# Address of
49		pushl %ebx			#  transfer buffer
50		xorl %eax,%eax			# Number of
51		movb %dh,%al			#  blocks to
52		pushl %eax			#  transfer
53		pushb $0x10			# Size of packet
54		movl %esp,%ebp			# Packet pointer
55		callwi(read)			# Read from disk
56		leaw1r(0x10,_bp_,_sp)		# Clear stack
57		lret				# To far caller
58
59# Bootstrap
60
61main:		cld				# String ops inc
62		xorl %ecx,%ecx			# Zero
63		movl %cx,%es			# Address
64		movl %cx,%ds			#  data
65		movl %cx,%ss			# Set up
66		movwir(start,_sp)		#  stack
67		movl %esp,%esi			# Source
68		movwir(MEM_REL,_di)		# Destination
69		incb %ch			# Word count
70		rep				# Copy
71		movsl				#  code
72		movwir(part4,_si)		# Partition
73		cmpb $0x80,%dl			# Hard drive?
74		jb main.4			# No
75		movb $0x1,%dh			# Block count
76		callwi(nread)			# Read MBR
77		movwir(0x1,_cx) 		# Two passes
78main.1: 	movwir(MEM_BUF+PRT_OFF,_si)	# Partition table
79		movb $0x1,%dh			# Partition
80main.2: 	cmpbi1(PRT_BSD,0x4,_si_)	# Our partition type?
81		jne main.3			# No
82		jecxz main.5			# If second pass
83		tstbi0(0x80,_si_)		# Active?
84		jnz main.5			# Yes
85main.3: 	addl $0x10,%esi 		# Next entry
86		incb %dh			# Partition
87		cmpb $0x1+PRT_NUM,%dh		# In table?
88		jb main.2			# Yes
89		decl %ecx			# Do two
90		jecxz main.1			#  passes
91		movwir(msg_part,_si)		# Message
92		jmp error			# Error
93main.4: 	xorl %edx,%edx			# Partition:drive
94main.5: 	movwrm(_dx,MEM_ARG)		# Save args
95		movb $0x10,%dh			# Sector count
96		callwi(nread)			# Read disk
97		movwir(MEM_BTX,_bx)		# BTX
98		movw1r(0xa,_bx_,_si)		# Point past
99		addl %ebx,%esi			#  it
100		movwir(MEM_USR+SIZ_PAG,_di)	# Client page 1
101		movwir(MEM_BTX+0xe*SIZ_SEC,_cx) # Byte
102		subl %esi,%ecx			#  count
103		rep				# Relocate
104		movsb				#  client
105		subl %edi,%ecx			# Byte count
106		xorb %al,%al			# Zero
107		rep				#  assumed
108		stosb				#  bss
109		callwi(seta20)			# Enable A20
110		jmpnwi(start+MEM_JMP-MEM_ORG)	# Start BTX
111
112# Enable A20
113
114seta20: 	cli				# Disable interrupts
115seta20.1:	inb $0x64,%al			# Get status
116		testb $0x2,%al			# Busy?
117		jnz seta20.1			# Yes
118		movb $0xd1,%al			# Command: Write
119		outb %al,$0x64			#  output port
120seta20.2:	inb $0x64,%al			# Get status
121		testb $0x2,%al			# Busy?
122		jnz seta20.2			# Yes
123		movb $0xdf,%al			# Enable
124		outb %al,$0x60			#  A20
125		sti				# Enable interrupts
126		ret				# To caller
127
128# Local read from disk
129
130nread:		movwir(MEM_BUF,_bx)		# Transfer buffer
131		movw1r(0x8,_si_,_ax)		# Get
132		movw1r(0xa,_si_,_cx)		#  LBA
133		pushl %cs			# Read from
134		callwi(xread.1) 		#  disk
135		jnc return			# If success
136		movwir(msg_read,_si)		# Message
137
138# Error exit
139
140error:		callwi(putstr)			# Display message
141		movwir(prompt,_si)		# Display
142		callwi(putstr)			#  prompt
143		xorb %ah,%ah			# BIOS: Get
144		int $0x16			#  keypress
145		int $0x19			# BIOS: Reboot
146
147# Display string
148
149putstr.0:	movwir(0x7,_bx) 		# Page:attribute
150		movb $0xe,%ah			# BIOS: Display
151		int $0x10			#  character
152putstr: 	lodsb				# Get char
153		testb %al,%al			# End of string?
154		jne putstr.0			# No
155
156ereturn:	movb $0x1,%ah			# Invalid
157		stc				#  argument
158return: 	ret				# To caller
159
160# Read from disk
161
162read:		cs_				# LBA support
163		tstbim(0x80,MEM_REL+flags-start)#  enabled?
164		jz read.1			# No
165		movwir(0x55aa,_bx)		# Magic
166		pushl %edx			# Save
167		movb $0x41,%ah			# BIOS: Check
168		int $0x13			#  extensions present
169		popl %edx			# Restore
170		jc read.1			# If error
171		cmpwir(0xaa55,_bx)		# Magic?
172		jne read.1			# No
173		testb $0x1,%cl			# Packet interface?
174		jz read.1			# No
175		movl %ebp,%esi			# Disk packet
176		movb $0x42,%ah			# BIOS: Extended
177		int $0x13			#  read
178		ret				# To caller
179
180read.1: 	pushl %edx			# Save
181		movb $0x8,%ah			# BIOS: Get drive
182		int $0x13			#  parameters
183		movb %dh,%ch			# Max head number
184		popl %edx			# Restore
185		jc return			# If error
186		andb $0x3f,%cl			# Sectors per track
187		jz ereturn			# If zero
188		cli				# Disable interrupts
189		o16				# Get
190		movw1r(0x8,_bp_,_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
199		divw %bx,%ax			#  of heads
200		movb %dl,%bh			# Head number
201		popl %edx			# Restore
202		o16				# Cylinder number
203		cmpl $0x3ff,%eax		#  supportable?
204		sti				# Enable interrupts
205		ja ereturn			# No
206		xchgb %al,%ah			# Set up cylinder
207		rorb $0x2,%al			#  number
208		orb %ch,%al			# Merge
209		incl %eax			#  sector
210		xchgl %eax,%ecx 		#  number
211		movb %bh,%dh			# Head number
212		subb %ah,%al			# Sectors this track
213		movb1r(0x2,_bp_,_ah)		# Blocks to read
214		cmpb %ah,%al			# To read
215		jb read.2			#  this
216		movb %ah,%al			#  track
217read.2: 	movwir(0x5,_di) 		# Try count
218read.3: 	lesw1r(0x4,_bp_,_bx)		# Transfer buffer
219		pushl %eax			# Save
220		movb $0x2,%ah			# BIOS: Read
221		int $0x13			#  from disk
222		popl %ebx			# Restore
223		jnc read.4			# If success
224		decl %edi			# Retry?
225		jz read.6			# No
226		xorb %ah,%ah			# BIOS: Reset
227		int $0x13			#  disk system
228		xchgl %ebx,%eax 		# Block count
229		jmp read.3			# Continue
230read.4: 	movzbl %bl,%eax 		# Sectors read
231		addwr1(_ax,0x8,_bp_)		# Adjust
232		jnc read.5			#  LBA,
233		incw1(0xa,_bp_) 		#  transfer
234read.5: 	shlb %bl			#  buffer
235		addbr1(_bl,0x5,_bp_)		#  pointer,
236		subbr1(_al,0x2,_bp_)		#  block count
237		ja read.1			# If not done
238read.6: 	ret				# To caller
239
240# Messages
241
242msg_read:	.asciz "Read"
243msg_part:	.asciz "Boot"
244
245prompt: 	.asciz " error\r\n"
246
247flags:		.byte FLAGS			# Flags
248
249		.org PRT_OFF,0x90
250
251# Partition table
252
253		.fill 0x30,0x1,0x0
254part4:		.byte 0x80, 0x00, 0x01, 0x00
255		.byte 0xa5, 0xff, 0xff, 0xff
256		.byte 0x00, 0x00, 0x00, 0x00
257		.byte 0x50, 0xc3, 0x00, 0x00
258
259		.word 0xaa55			# Magic number
260