1172940Sjhb/*-
2172940Sjhb * Copyright (c) 2007 Yahoo!, Inc.
3172940Sjhb * All rights reserved.
4172940Sjhb * Written by: John Baldwin <jhb@FreeBSD.org>
5172940Sjhb *
6172940Sjhb * Redistribution and use in source and binary forms, with or without
7172940Sjhb * modification, are permitted provided that the following conditions
8172940Sjhb * are met:
9172940Sjhb * 1. Redistributions of source code must retain the above copyright
10172940Sjhb *    notice, this list of conditions and the following disclaimer.
11172940Sjhb * 2. Redistributions in binary form must reproduce the above copyright
12172940Sjhb *    notice, this list of conditions and the following disclaimer in the
13172940Sjhb *    documentation and/or other materials provided with the distribution.
14172940Sjhb * 3. Neither the name of the author nor the names of any co-contributors
15172940Sjhb *    may be used to endorse or promote products derived from this software
16172940Sjhb *    without specific prior written permission.
17172940Sjhb *
18172940Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19172940Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20172940Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21172940Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22172940Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23172940Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24172940Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25172940Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26172940Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27172940Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28172940Sjhb * SUCH DAMAGE.
29172940Sjhb *
30172940Sjhb * $FreeBSD: releng/10.3/sys/boot/i386/gptboot/gptldr.S 289358 2015-10-15 03:48:03Z cperciva $
31173957Sjhb *
32173957Sjhb * Partly from: src/sys/boot/i386/boot2/boot1.S 1.31
33172940Sjhb */
34172940Sjhb
35172940Sjhb/* Memory Locations */
36172940Sjhb		.set MEM_REL,0x700		# Relocation address
37172940Sjhb		.set MEM_ARG,0x900		# Arguments
38172940Sjhb		.set MEM_ORG,0x7c00		# Origin
39172940Sjhb		.set MEM_BUF,0x8cec		# Load area
40172940Sjhb		.set MEM_BTX,0x9000		# BTX start
41172940Sjhb		.set MEM_JMP,0x9010		# BTX entry point
42172940Sjhb		.set MEM_USR,0xa000		# Client start
43172940Sjhb		.set BDA_BOOT,0x472		# Boot howto flag
44172940Sjhb
45172940Sjhb/* Misc. Constants */
46172940Sjhb		.set SIZ_PAG,0x1000		# Page size
47172940Sjhb		.set SIZ_SEC,0x200		# Sector size
48289358Scperciva		.set COPY_BLKS,0x4		# Number of blocks
49289358Scperciva						# to copy for boot2
50289358Scperciva		.set COPY_BLK_SZ,0x8000		# Copy in 32k blocks; must be
51289358Scperciva						# a multiple of 16 bytes
52172940Sjhb
53172940Sjhb		.globl start
54172940Sjhb		.code16
55172940Sjhb
56172940Sjhb/*
57172940Sjhb * Copy BTX and boot2 to the right locations and start it all up.
58172940Sjhb */
59172940Sjhb
60172940Sjhb/*
61172940Sjhb * Setup the segment registers to flat addressing (segment 0) and setup the
62172940Sjhb * stack to end just below the start of our code.
63172940Sjhb */
64172940Sjhbstart:		xor %cx,%cx			# Zero
65172940Sjhb		mov %cx,%es			# Address
66172940Sjhb		mov %cx,%ds			#  data
67172940Sjhb		mov %cx,%ss			# Set up
68172940Sjhb		mov $start,%sp			#  stack
69172940Sjhb
70172940Sjhb/*
71172940Sjhb * BTX is right after us at 'end'.  We read the length of BTX out of
72172940Sjhb * its header to find boot2.  We need to copy boot2 to MEM_USR and BTX
73172940Sjhb * to MEM_BTX.  Since those might overlap, we have to copy boot2
74172940Sjhb * backwards first and then copy BTX.  We aren't sure exactly how long
75289358Scperciva * boot2 is, but it's currently under 128kB so we'll copy 4 blocks of 32kB
76289358Scperciva * each; this can be adjusted via COPY_BLK and COPY_BLK_SZ above.
77172940Sjhb */
78172940Sjhb		mov $end,%bx			# BTX
79172940Sjhb		mov 0xa(%bx),%si		# Get BTX length and set
80172940Sjhb		add %bx,%si			#  %si to start of boot2
81289358Scperciva		dec %si				# Set %ds:%si to point at the
82289358Scperciva		mov %si,%ax			# last byte we want to copy
83289358Scperciva		shr $4,%ax			# from boot2, with %si made as
84289358Scperciva		add $(COPY_BLKS*COPY_BLK_SZ/16),%ax	# small as possible.
85289358Scperciva		and $0xf,%si			#
86289358Scperciva		mov %ax,%ds			#
87289358Scperciva		mov $MEM_USR/16,%ax		# Set %es:(-1) to point at
88289358Scperciva		add $(COPY_BLKS*COPY_BLK_SZ/16),%ax	# the last byte we
89289358Scperciva		mov %ax,%es			# want to copy boot2 into.
90289358Scperciva		mov $COPY_BLKS,%bx		# Copy COPY_BLKS 32k blocks
91289358Scpercivacopyloop:
92289358Scperciva		add $COPY_BLK_SZ,%si		# Adjust %ds:%si to point at
93289358Scperciva		mov %ds,%ax			# the end of the next 32k to
94289358Scperciva		sub $COPY_BLK_SZ/16,%ax		# copy from boot2
95289358Scperciva		mov %ax,%ds
96289358Scperciva		mov $COPY_BLK_SZ-1,%di		# Adjust %es:%di to point at
97289358Scperciva		mov %es,%ax			# the end of the next 32k into
98289358Scperciva		sub $COPY_BLK_SZ/16,%ax		# which we want boot2 copied
99172940Sjhb		mov %ax,%es
100289358Scperciva		mov $COPY_BLK_SZ,%cx		# Copy 32k
101172940Sjhb		std
102172940Sjhb		rep movsb
103289358Scperciva		dec %bx
104289358Scperciva		jnz copyloop
105172940Sjhb		mov %cx,%ds			# Reset %ds and %es
106172940Sjhb		mov %cx,%es
107289358Scperciva		mov $end,%bx			# BTX
108172940Sjhb		mov 0xa(%bx),%cx		# Get BTX length and set
109172940Sjhb		mov %bx,%si			#  %si to end of BTX
110172940Sjhb		mov $MEM_BTX,%di		# %di -> end of BTX at
111172940Sjhb		add %cx,%si			#  MEM_BTX
112172940Sjhb		add %cx,%di
113172940Sjhb		dec %si
114172940Sjhb		dec %di
115172940Sjhb		rep movsb			# Move BTX
116172940Sjhb		cld				# String ops inc
117172940Sjhb/*
118172940Sjhb * Enable A20 so we can access memory above 1 meg.
119172940Sjhb * Use the zero-valued %cx as a timeout for embedded hardware which do not
120172940Sjhb * have a keyboard controller.
121172940Sjhb */
122172940Sjhbseta20: 	cli				# Disable interrupts
123172940Sjhbseta20.1:	dec %cx				# Timeout?
124172940Sjhb		jz seta20.3			# Yes
125172940Sjhb		inb $0x64,%al			# Get status
126172940Sjhb		testb $0x2,%al			# Busy?
127172940Sjhb		jnz seta20.1			# Yes
128172940Sjhb		movb $0xd1,%al			# Command: Write
129172940Sjhb		outb %al,$0x64			#  output port
130172940Sjhbseta20.2:	inb $0x64,%al			# Get status
131172940Sjhb		testb $0x2,%al			# Busy?
132172940Sjhb		jnz seta20.2			# Yes
133172940Sjhb		movb $0xdf,%al			# Enable
134172940Sjhb		outb %al,$0x60			#  A20
135172940Sjhbseta20.3:	sti				# Enable interrupts
136172940Sjhb
137172940Sjhb/*
138172940Sjhb * Save drive number from BIOS so boot2 can see it and start BTX.
139172940Sjhb */
140172940Sjhb		movb %dl,MEM_ARG
141172940Sjhb		jmp MEM_JMP			# Start BTX
142172940Sjhbend:
143