xref: /dragonfly/stand/boot/pc32/btx/btxldr/btxldr.S (revision 479ab7f0)
1*479ab7f0SSascha Wildner/*
2*479ab7f0SSascha Wildner * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
3*479ab7f0SSascha Wildner *
4*479ab7f0SSascha Wildner * This code is derived from software contributed to The DragonFly Project
5*479ab7f0SSascha Wildner * by Matthew Dillon <dillon@backplane.com>
6*479ab7f0SSascha Wildner *
7*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms, with or without
8*479ab7f0SSascha Wildner * modification, are permitted provided that the following conditions
9*479ab7f0SSascha Wildner * are met:
10*479ab7f0SSascha Wildner *
11*479ab7f0SSascha Wildner * 1. Redistributions of source code must retain the above copyright
12*479ab7f0SSascha Wildner *    notice, this list of conditions and the following disclaimer.
13*479ab7f0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
14*479ab7f0SSascha Wildner *    notice, this list of conditions and the following disclaimer in
15*479ab7f0SSascha Wildner *    the documentation and/or other materials provided with the
16*479ab7f0SSascha Wildner *    distribution.
17*479ab7f0SSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its
18*479ab7f0SSascha Wildner *    contributors may be used to endorse or promote products derived
19*479ab7f0SSascha Wildner *    from this software without specific, prior written permission.
20*479ab7f0SSascha Wildner *
21*479ab7f0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*479ab7f0SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*479ab7f0SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*479ab7f0SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*479ab7f0SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*479ab7f0SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*479ab7f0SSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*479ab7f0SSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*479ab7f0SSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*479ab7f0SSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*479ab7f0SSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*479ab7f0SSascha Wildner * SUCH DAMAGE.
33*479ab7f0SSascha Wildner *
34*479ab7f0SSascha Wildner * Copyright (c) 1998 Robert Nordier
35*479ab7f0SSascha Wildner * All rights reserved.
36*479ab7f0SSascha Wildner *
37*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms are freely
38*479ab7f0SSascha Wildner * permitted provided that the above copyright notice and this
39*479ab7f0SSascha Wildner * paragraph and the following disclaimer are duplicated in all
40*479ab7f0SSascha Wildner * such forms.
41*479ab7f0SSascha Wildner *
42*479ab7f0SSascha Wildner * This software is provided "AS IS" and without any express or
43*479ab7f0SSascha Wildner * implied warranties, including, without limitation, the implied
44*479ab7f0SSascha Wildner * warranties of merchantability and fitness for a particular
45*479ab7f0SSascha Wildner * purpose.
46*479ab7f0SSascha Wildner *
47*479ab7f0SSascha Wildner * $FreeBSD: src/sys/boot/i386/btx/btxldr/Makefile,v 1.17 2004/04/27 19:45:16 ru Exp $
48*479ab7f0SSascha Wildner * $DragonFly: src/sys/boot/pc32/btx/btxldr/btxldr.S,v 1.3 2004/07/19 23:30:34 dillon Exp $
49*479ab7f0SSascha Wildner */
50*479ab7f0SSascha Wildner
51*479ab7f0SSascha Wildner/*
52*479ab7f0SSascha Wildner * Prototype BTX loader program, written in a couple of hours.  The
53*479ab7f0SSascha Wildner * real thing should probably be more flexible, and in C.
54*479ab7f0SSascha Wildner */
55*479ab7f0SSascha Wildner
56*479ab7f0SSascha Wildner#include "../../bootasm.h"
57*479ab7f0SSascha Wildner/*
58*479ab7f0SSascha Wildner * Memory locations.
59*479ab7f0SSascha Wildner */
60*479ab7f0SSascha Wildner		.set MEM_DATA,start+0x1000	# Data segment
61*479ab7f0SSascha Wildner/*
62*479ab7f0SSascha Wildner * Segment selectors.
63*479ab7f0SSascha Wildner */
64*479ab7f0SSascha Wildner		.set SEL_SCODE,0x8		# 4GB code
65*479ab7f0SSascha Wildner		.set SEL_SDATA,0x10		# 4GB data
66*479ab7f0SSascha Wildner		.set SEL_RCODE,0x18		# 64K code
67*479ab7f0SSascha Wildner		.set SEL_RDATA,0x20		# 64K data
68*479ab7f0SSascha Wildner/*
69*479ab7f0SSascha Wildner * Paging constants.
70*479ab7f0SSascha Wildner */
71*479ab7f0SSascha Wildner		.set PAG_SIZ,0x1000		# Page size
72*479ab7f0SSascha Wildner		.set PAG_ENT,0x4		# Page entry size
73*479ab7f0SSascha Wildner/*
74*479ab7f0SSascha Wildner * Screen constants.
75*479ab7f0SSascha Wildner */
76*479ab7f0SSascha Wildner		.set SCR_MAT,0x7		# Mode/attribute
77*479ab7f0SSascha Wildner		.set SCR_COL,0x50		# Columns per row
78*479ab7f0SSascha Wildner		.set SCR_ROW,0x19		# Rows per screen
79*479ab7f0SSascha Wildner/*
80*479ab7f0SSascha Wildner * Required by aout gas inadequacy.
81*479ab7f0SSascha Wildner */
82*479ab7f0SSascha Wildner		.set SIZ_STUB,0x1a		# Size of stub
83*479ab7f0SSascha Wildner/*
84*479ab7f0SSascha Wildner * We expect to be loaded by boot2 at the origin defined in ./Makefile.
85*479ab7f0SSascha Wildner * This is typically 0x200000.
86*479ab7f0SSascha Wildner *
87*479ab7f0SSascha Wildner * I *THINK* (not sure) that execution begins with us in 'virtual mode',
88*479ab7f0SSascha Wildner * meaning everything is offset by MEM_BTX_USR.  We will load a gdt to
89*479ab7f0SSascha Wildner * set the base offsets back to 0.
90*479ab7f0SSascha Wildner */
91*479ab7f0SSascha Wildner		.globl start
92*479ab7f0SSascha Wildner/*
93*479ab7f0SSascha Wildner * BTX program loader for ELF clients.
94*479ab7f0SSascha Wildner */
95*479ab7f0SSascha Wildnerstart:		cld				# String ops inc
96*479ab7f0SSascha Wildner		movl $m_logo,%esi		# Identify
97*479ab7f0SSascha Wildner		call putstr			#  ourselves
98*479ab7f0SSascha Wildner#if !defined(MEM_BTX_USR_STK)
99*479ab7f0SSascha Wildner		movzwl BDA_MEM,%eax		# Get base memory
100*479ab7f0SSascha Wildner		decl %eax
101*479ab7f0SSascha Wildner		shll $0xa,%eax			# Convert to bytes
102*479ab7f0SSascha Wildner#else
103*479ab7f0SSascha Wildner		movl $MEM_BTX_USR_STK,%eax
104*479ab7f0SSascha Wildner#endif
105*479ab7f0SSascha Wildner		movl %eax,%ebp			# Base of user stack
106*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
107*479ab7f0SSascha Wildner		movl $m_mem,%esi		# Display
108*479ab7f0SSascha Wildner		call hexout			#  amount of
109*479ab7f0SSascha Wildner		call putstr			#  base memory
110*479ab7f0SSascha Wildner#endif
111*479ab7f0SSascha Wildner
112*479ab7f0SSascha Wildner		/*
113*479ab7f0SSascha Wildner		 * Load a new GDT.  XXX what does this do to running code
114*479ab7f0SSascha Wildner		 * segments?  What if an interrupt occurs?  What if the
115*479ab7f0SSascha Wildner		 * segment registers are reloaded?
116*479ab7f0SSascha Wildner		 */
117*479ab7f0SSascha Wildner		lgdt gdtdesc
118*479ab7f0SSascha Wildner
119*479ab7f0SSascha Wildner		/*
120*479ab7f0SSascha Wildner		 * Relocate caller's arguments.
121*479ab7f0SSascha Wildner		 */
122*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
123*479ab7f0SSascha Wildner		movl $m_esp,%esi		# Display
124*479ab7f0SSascha Wildner		movl %esp,%eax			#  caller
125*479ab7f0SSascha Wildner		call hexout			#  stack
126*479ab7f0SSascha Wildner		call putstr			#  pointer
127*479ab7f0SSascha Wildner		movl $m_args,%esi		# Format string
128*479ab7f0SSascha Wildner		leal 0x4(%esp,1),%ebx		# First argument
129*479ab7f0SSascha Wildner		movl $0x6,%ecx			# Count
130*479ab7f0SSascha Wildnerstart.1:	movl (%ebx),%eax		# Get argument and
131*479ab7f0SSascha Wildner		addl $0x4,%ebx			#  bump pointer
132*479ab7f0SSascha Wildner		call hexout			# Display it
133*479ab7f0SSascha Wildner		loop start.1			# Till done
134*479ab7f0SSascha Wildner		call putstr			# End message
135*479ab7f0SSascha Wildner#endif
136*479ab7f0SSascha Wildner		/*
137*479ab7f0SSascha Wildner		 * Arguments: (entry, boothowto, bootdev, 0, 0, 0, bootinfo)
138*479ab7f0SSascha Wildner		 *		0x00,  0x04,      0x08,             0x18
139*479ab7f0SSascha Wildner		 *
140*479ab7f0SSascha Wildner		 * sizeof(bootinfo) == 0x48 (BOOTINFO_SIZE)
141*479ab7f0SSascha Wildner		 * sizeof arguments == 0x18 (MEM_ARG_SIZE)
142*479ab7f0SSascha Wildner		 * total arguments  == 0x60 bytes (USR_ARGOFFSET)
143*479ab7f0SSascha Wildner		 */
144*479ab7f0SSascha Wildner
145*479ab7f0SSascha Wildner		movl $BOOTINFO_SIZE,%ecx 	# Allocate space
146*479ab7f0SSascha Wildner		subl %ecx,%ebp			#  for bootinfo
147*479ab7f0SSascha Wildner		movl 0x18(%esp,1),%esi		# Source: bootinfo
148*479ab7f0SSascha Wildner		cmpl $0x0, %esi			# If the bootinfo pointer
149*479ab7f0SSascha Wildner		je start_null_bi		#  is null, do not copy it
150*479ab7f0SSascha Wildner		movl %ebp,%edi			# Destination
151*479ab7f0SSascha Wildner		rep				# Copy
152*479ab7f0SSascha Wildner		movsb				#  it
153*479ab7f0SSascha Wildner		movl %ebp,0x18(%esp,1)		# Update pointer
154*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
155*479ab7f0SSascha Wildner		movl $m_rel_bi,%esi		# Display
156*479ab7f0SSascha Wildner		movl %ebp,%eax			#  bootinfo
157*479ab7f0SSascha Wildner		call hexout			#  relocation
158*479ab7f0SSascha Wildner		call putstr			#  message
159*479ab7f0SSascha Wildner#endif
160*479ab7f0SSascha Wildnerstart_null_bi:	movl $0x18,%ecx 		# Allocate space
161*479ab7f0SSascha Wildner		subl %ecx,%ebp			#  for arguments
162*479ab7f0SSascha Wildner		leal 0x4(%esp,1),%esi		# Source
163*479ab7f0SSascha Wildner		movl %ebp,%edi			# Destination
164*479ab7f0SSascha Wildner		rep				# Copy
165*479ab7f0SSascha Wildner		movsb				#  them
166*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
167*479ab7f0SSascha Wildner		movl $m_rel_args,%esi		# Display
168*479ab7f0SSascha Wildner		movl %ebp,%eax			#  argument
169*479ab7f0SSascha Wildner		call hexout			#  relocation
170*479ab7f0SSascha Wildner		call putstr			#  message
171*479ab7f0SSascha Wildner#endif
172*479ab7f0SSascha Wildner/*
173*479ab7f0SSascha Wildner * Set up BTX kernel.
174*479ab7f0SSascha Wildner */
175*479ab7f0SSascha Wildner		movl $MEM_BTX_ESP,%esp		# Set up new stack
176*479ab7f0SSascha Wildner		movl $MEM_DATA,%ebx		# Data segment
177*479ab7f0SSascha Wildner		movl $m_vers,%esi		# Display BTX
178*479ab7f0SSascha Wildner		call putstr			#  version message
179*479ab7f0SSascha Wildner		movb 0x5(%ebx),%al		# Get major version
180*479ab7f0SSascha Wildner		addb $'0',%al			# Display
181*479ab7f0SSascha Wildner		call putchr			#  it
182*479ab7f0SSascha Wildner		movb $'.',%al			# And a
183*479ab7f0SSascha Wildner		call putchr			#  dot
184*479ab7f0SSascha Wildner		movb 0x6(%ebx),%al		# Get minor
185*479ab7f0SSascha Wildner		xorb %ah,%ah			#  version
186*479ab7f0SSascha Wildner		movb $0xa,%dl			# Divide
187*479ab7f0SSascha Wildner		divb %dl,%al			#  by 10
188*479ab7f0SSascha Wildner		addb $'0',%al			# Display
189*479ab7f0SSascha Wildner		call putchr			#  tens
190*479ab7f0SSascha Wildner		movb %ah,%al			# Get units
191*479ab7f0SSascha Wildner		addb $'0',%al			# Display
192*479ab7f0SSascha Wildner		call putchr			#  units
193*479ab7f0SSascha Wildner		call putstr			# End message
194*479ab7f0SSascha Wildner
195*479ab7f0SSascha Wildner		# Relocate the BTX image from wherever it was loaded (%ebx),
196*479ab7f0SSascha Wildner		# which is typically offset 0x1000 in the load data, to
197*479ab7f0SSascha Wildner		# MEM_BTX_ORG (typically 0x9000).
198*479ab7f0SSascha Wildner		#
199*479ab7f0SSascha Wildner		# MEM_BTX_TBL + ((mappages | 0x3ff) + 1) * 4
200*479ab7f0SSascha Wildner		# mappages is typically 0x0ffn so we get 0x1000*4 = 0x4000
201*479ab7f0SSascha Wildner		# MEM_BTX_TBL is traditionally mapped at 0x5000 so the
202*479ab7f0SSascha Wildner		# whole calculation translated to MEM_BTX_ORG (0x9000).
203*479ab7f0SSascha Wildner#if 0
204*479ab7f0SSascha Wildner		/* XXX what is all of this junk? */
205*479ab7f0SSascha Wildner		movzwl 0x8(%ebx),%edi		# Compute the BTX load address
206*479ab7f0SSascha Wildner		orl $PAG_SIZ/PAG_ENT-1,%edi	# (by skipping the page table)
207*479ab7f0SSascha Wildner		incl %edi
208*479ab7f0SSascha Wildner		shll $0x2,%edi
209*479ab7f0SSascha Wildner		addl $MEM_BTX_TBL,%edi
210*479ab7f0SSascha Wildner#else
211*479ab7f0SSascha Wildner		movl $MEM_BTX_ORG,%edi
212*479ab7f0SSascha Wildner#endif
213*479ab7f0SSascha Wildner		movl %ebx,%esi			# %esi = BTX image source
214*479ab7f0SSascha Wildner		pushl %edi			# Save load address
215*479ab7f0SSascha Wildner		movzwl 0xa(%ebx),%ecx		# Image size (bytes)
216*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
217*479ab7f0SSascha Wildner		pushl %ecx			# Save image size
218*479ab7f0SSascha Wildner#endif
219*479ab7f0SSascha Wildner		rep				# Relocate BTX
220*479ab7f0SSascha Wildner		movsb
221*479ab7f0SSascha Wildner		movl %esi,%ebx			# Keep place
222*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
223*479ab7f0SSascha Wildner		movl $m_rel_btx,%esi		# Restore
224*479ab7f0SSascha Wildner		popl %eax			#  parameters
225*479ab7f0SSascha Wildner		call hexout			#  and
226*479ab7f0SSascha Wildner#endif
227*479ab7f0SSascha Wildner		popl %ebp			#  display
228*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
229*479ab7f0SSascha Wildner		movl %ebp,%eax			#  the
230*479ab7f0SSascha Wildner		call hexout			#  relocation
231*479ab7f0SSascha Wildner		call putstr			#  message
232*479ab7f0SSascha Wildner#endif
233*479ab7f0SSascha Wildner		/*
234*479ab7f0SSascha Wildner		 * ADJUST EBP FOR USER BASE ADDRESS
235*479ab7f0SSascha Wildner		 *
236*479ab7f0SSascha Wildner		 * XXX why not just move MEM_BTX_USR into %ebp ?
237*479ab7f0SSascha Wildner		 */
238*479ab7f0SSascha Wildner		addl $MEM_BTX_USR-MEM_BTX_ORG,%ebp
239*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
240*479ab7f0SSascha Wildner		movl $m_base,%esi		#  the
241*479ab7f0SSascha Wildner		movl %ebp,%eax			#  user
242*479ab7f0SSascha Wildner		call hexout			#  base
243*479ab7f0SSascha Wildner		call putstr			#  address
244*479ab7f0SSascha Wildner#endif
245*479ab7f0SSascha Wildner/*
246*479ab7f0SSascha Wildner * Set up ELF-format client program.
247*479ab7f0SSascha Wildner */
248*479ab7f0SSascha Wildner		cmpl $0x464c457f,(%ebx) 	# ELF magic number?
249*479ab7f0SSascha Wildner		je start.3			# Yes
250*479ab7f0SSascha Wildner		movl $e_fmt,%esi		# Display error
251*479ab7f0SSascha Wildner		call putstr			#  message
252*479ab7f0SSascha Wildnerstart.2:	jmp start.2			# Hang
253*479ab7f0SSascha Wildnerstart.3:
254*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
255*479ab7f0SSascha Wildner		movl $m_elf,%esi		# Display ELF
256*479ab7f0SSascha Wildner		call putstr			#  message
257*479ab7f0SSascha Wildner		movl $m_segs,%esi		# Format string
258*479ab7f0SSascha Wildner#endif
259*479ab7f0SSascha Wildner		movl $0x2,%edi			# Segment count
260*479ab7f0SSascha Wildner		movl 0x1c(%ebx),%edx		# Get e_phoff
261*479ab7f0SSascha Wildner		addl %ebx,%edx			# To pointer
262*479ab7f0SSascha Wildner		movzwl 0x2c(%ebx),%ecx		# Get e_phnum
263*479ab7f0SSascha Wildnerstart.4:	cmpl $0x1,(%edx)		# Is p_type PT_LOAD?
264*479ab7f0SSascha Wildner		jne start.6			# No
265*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
266*479ab7f0SSascha Wildner		movl 0x4(%edx),%eax		# Display
267*479ab7f0SSascha Wildner		call hexout			#  p_offset
268*479ab7f0SSascha Wildner		movl 0x8(%edx),%eax		# Display
269*479ab7f0SSascha Wildner		call hexout			#  p_vaddr
270*479ab7f0SSascha Wildner		movl 0x10(%edx),%eax		# Display
271*479ab7f0SSascha Wildner		call hexout			#  p_filesz
272*479ab7f0SSascha Wildner		movl 0x14(%edx),%eax		# Display
273*479ab7f0SSascha Wildner		call hexout			#  p_memsz
274*479ab7f0SSascha Wildner		call putstr			# End message
275*479ab7f0SSascha Wildner#endif
276*479ab7f0SSascha Wildner		pushl %esi			# Save
277*479ab7f0SSascha Wildner		pushl %edi			#  working
278*479ab7f0SSascha Wildner		pushl %ecx			#  registers
279*479ab7f0SSascha Wildner		movl 0x4(%edx),%esi		# Get p_offset
280*479ab7f0SSascha Wildner		addl %ebx,%esi			#  as pointer
281*479ab7f0SSascha Wildner		movl 0x8(%edx),%edi		# Get p_vaddr
282*479ab7f0SSascha Wildner		addl %ebp,%edi			#  as pointer
283*479ab7f0SSascha Wildner		movl 0x10(%edx),%ecx		# Get p_filesz
284*479ab7f0SSascha Wildner		rep				# Set up
285*479ab7f0SSascha Wildner		movsb				#  segment
286*479ab7f0SSascha Wildner		movl 0x14(%edx),%ecx		# Any bytes
287*479ab7f0SSascha Wildner		subl 0x10(%edx),%ecx		#  to zero?
288*479ab7f0SSascha Wildner		jz start.5			# No
289*479ab7f0SSascha Wildner		xorb %al,%al			# Then
290*479ab7f0SSascha Wildner		rep				#  zero
291*479ab7f0SSascha Wildner		stosb				#  them
292*479ab7f0SSascha Wildnerstart.5:	popl %ecx			# Restore
293*479ab7f0SSascha Wildner		popl %edi			#  working
294*479ab7f0SSascha Wildner		popl %esi			#  registers
295*479ab7f0SSascha Wildner		decl %edi			# Segments to do
296*479ab7f0SSascha Wildner		je start.7			# If none
297*479ab7f0SSascha Wildnerstart.6:	addl $0x20,%edx 		# To next entry
298*479ab7f0SSascha Wildner		loop start.4			# Till done
299*479ab7f0SSascha Wildnerstart.7:
300*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
301*479ab7f0SSascha Wildner		movl $m_done,%esi		# Display done
302*479ab7f0SSascha Wildner		call putstr			#  message
303*479ab7f0SSascha Wildner#endif
304*479ab7f0SSascha Wildner		movl $start.8,%esi		# Real mode stub
305*479ab7f0SSascha Wildner		movl $BOOT0_ORIGIN,%edi		# Destination
306*479ab7f0SSascha Wildner		movl $start.9-start.8,%ecx	# Size
307*479ab7f0SSascha Wildner		rep				# Relocate
308*479ab7f0SSascha Wildner		movsb				#  it
309*479ab7f0SSascha Wildner		ljmp $SEL_RCODE,$BOOT0_ORIGIN	# To 16-bit code
310*479ab7f0SSascha Wildner		.code16
311*479ab7f0SSascha Wildnerstart.8:	xorw %ax,%ax			# Data
312*479ab7f0SSascha Wildner		movb $SEL_RDATA,%al		#  selector
313*479ab7f0SSascha Wildner		movw %ax,%ss			# Reload SS
314*479ab7f0SSascha Wildner		movw %ax,%ds			# Reset
315*479ab7f0SSascha Wildner		movw %ax,%es			#  other
316*479ab7f0SSascha Wildner		movw %ax,%fs			#  segment
317*479ab7f0SSascha Wildner		movw %ax,%gs			#  limits
318*479ab7f0SSascha Wildner		movl %cr0,%eax			# Switch to
319*479ab7f0SSascha Wildner		decw %ax			#  real
320*479ab7f0SSascha Wildner		movl %eax,%cr0			#  mode
321*479ab7f0SSascha Wildner		ljmp $0,$MEM_BTX_ENTRY		# Jump to BTX entry point
322*479ab7f0SSascha Wildnerstart.9:
323*479ab7f0SSascha Wildner		.code32
324*479ab7f0SSascha Wildner/*
325*479ab7f0SSascha Wildner * Output message [ESI] followed by EAX in hex.
326*479ab7f0SSascha Wildner */
327*479ab7f0SSascha Wildnerhexout: 	pushl %eax			# Save
328*479ab7f0SSascha Wildner		call putstr			# Display message
329*479ab7f0SSascha Wildner		popl %eax			# Restore
330*479ab7f0SSascha Wildner		pushl %esi			# Save
331*479ab7f0SSascha Wildner		pushl %edi			# callers
332*479ab7f0SSascha Wildner		movl $buf,%edi			# Buffer
333*479ab7f0SSascha Wildner		pushl %edi			# Save
334*479ab7f0SSascha Wildner		call hex32			# To hex
335*479ab7f0SSascha Wildner		xorb %al,%al			# Terminate
336*479ab7f0SSascha Wildner		stosb				#  string
337*479ab7f0SSascha Wildner		popl %esi			# Restore
338*479ab7f0SSascha Wildnerhexout.1:	lodsb				# Get a char
339*479ab7f0SSascha Wildner		cmpb $'0',%al			# Leading zero?
340*479ab7f0SSascha Wildner		je hexout.1			# Yes
341*479ab7f0SSascha Wildner		testb %al,%al			# End of string?
342*479ab7f0SSascha Wildner		jne hexout.2			# No
343*479ab7f0SSascha Wildner		decl %esi			# Undo
344*479ab7f0SSascha Wildnerhexout.2:	decl %esi			# Adjust for inc
345*479ab7f0SSascha Wildner		call putstr			# Display hex
346*479ab7f0SSascha Wildner		popl %edi			# Restore
347*479ab7f0SSascha Wildner		popl %esi			# callers
348*479ab7f0SSascha Wildner		ret				# To caller
349*479ab7f0SSascha Wildner/*
350*479ab7f0SSascha Wildner * Output zero-terminated string [ESI] to the console.
351*479ab7f0SSascha Wildner */
352*479ab7f0SSascha Wildnerputstr.0:	call putchr			# Output char
353*479ab7f0SSascha Wildnerputstr: 	lodsb				# Load char
354*479ab7f0SSascha Wildner		testb %al,%al			# End of string?
355*479ab7f0SSascha Wildner		jne putstr.0			# No
356*479ab7f0SSascha Wildner		ret				# To caller
357*479ab7f0SSascha Wildner/*
358*479ab7f0SSascha Wildner * Output character AL to the console.
359*479ab7f0SSascha Wildner */
360*479ab7f0SSascha Wildnerputchr: 	pusha				# Save
361*479ab7f0SSascha Wildner		xorl %ecx,%ecx			# Zero for loops
362*479ab7f0SSascha Wildner		movb $SCR_MAT,%ah		# Mode/attribute
363*479ab7f0SSascha Wildner		movl $BDA_POS,%ebx		# BDA pointer
364*479ab7f0SSascha Wildner		movw (%ebx),%dx 		# Cursor position
365*479ab7f0SSascha Wildner		movl $0xb8000,%edi		# Regen buffer (color)
366*479ab7f0SSascha Wildner		cmpb %ah,BDA_SCR-BDA_POS(%ebx)	# Mono mode?
367*479ab7f0SSascha Wildner		jne putchr.1			# No
368*479ab7f0SSascha Wildner		xorw %di,%di			# Regen buffer (mono)
369*479ab7f0SSascha Wildnerputchr.1:	cmpb $0xa,%al			# New line?
370*479ab7f0SSascha Wildner		je putchr.2			# Yes
371*479ab7f0SSascha Wildner		xchgl %eax,%ecx 		# Save char
372*479ab7f0SSascha Wildner		movb $SCR_COL,%al		# Columns per row
373*479ab7f0SSascha Wildner		mulb %dh			#  * row position
374*479ab7f0SSascha Wildner		addb %dl,%al			#  + column
375*479ab7f0SSascha Wildner		adcb $0x0,%ah			#  position
376*479ab7f0SSascha Wildner		shll %eax			#  * 2
377*479ab7f0SSascha Wildner		xchgl %eax,%ecx 		# Swap char, offset
378*479ab7f0SSascha Wildner		movw %ax,(%edi,%ecx,1)		# Write attr:char
379*479ab7f0SSascha Wildner		incl %edx			# Bump cursor
380*479ab7f0SSascha Wildner		cmpb $SCR_COL,%dl		# Beyond row?
381*479ab7f0SSascha Wildner		jb putchr.3			# No
382*479ab7f0SSascha Wildnerputchr.2:	xorb %dl,%dl			# Zero column
383*479ab7f0SSascha Wildner		incb %dh			# Bump row
384*479ab7f0SSascha Wildnerputchr.3:	cmpb $SCR_ROW,%dh		# Beyond screen?
385*479ab7f0SSascha Wildner		jb putchr.4			# No
386*479ab7f0SSascha Wildner		leal 2*SCR_COL(%edi),%esi	# New top line
387*479ab7f0SSascha Wildner		movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
388*479ab7f0SSascha Wildner		rep				# Scroll
389*479ab7f0SSascha Wildner		movsl				#  screen
390*479ab7f0SSascha Wildner		movb $' ',%al			# Space
391*479ab7f0SSascha Wildner		movb $SCR_COL,%cl		# Columns to clear
392*479ab7f0SSascha Wildner		rep				# Clear
393*479ab7f0SSascha Wildner		stosw				#  line
394*479ab7f0SSascha Wildner		movb $SCR_ROW-1,%dh		# Bottom line
395*479ab7f0SSascha Wildnerputchr.4:	movw %dx,(%ebx) 		# Update position
396*479ab7f0SSascha Wildner		popa				# Restore
397*479ab7f0SSascha Wildner		ret				# To caller
398*479ab7f0SSascha Wildner/*
399*479ab7f0SSascha Wildner * Convert EAX, AX, or AL to hex, saving the result to [EDI].
400*479ab7f0SSascha Wildner */
401*479ab7f0SSascha Wildnerhex32:		pushl %eax			# Save
402*479ab7f0SSascha Wildner		shrl $0x10,%eax 		# Do upper
403*479ab7f0SSascha Wildner		call hex16			#  16
404*479ab7f0SSascha Wildner		popl %eax			# Restore
405*479ab7f0SSascha Wildnerhex16:		call hex16.1			# Do upper 8
406*479ab7f0SSascha Wildnerhex16.1:	xchgb %ah,%al			# Save/restore
407*479ab7f0SSascha Wildnerhex8:		pushl %eax			# Save
408*479ab7f0SSascha Wildner		shrb $0x4,%al			# Do upper
409*479ab7f0SSascha Wildner		call hex8.1			#  4
410*479ab7f0SSascha Wildner		popl %eax			# Restore
411*479ab7f0SSascha Wildnerhex8.1: 	andb $0xf,%al			# Get lower 4
412*479ab7f0SSascha Wildner		cmpb $0xa,%al			# Convert
413*479ab7f0SSascha Wildner		sbbb $0x69,%al			#  to hex
414*479ab7f0SSascha Wildner		das				#  digit
415*479ab7f0SSascha Wildner		orb $0x20,%al			# To lower case
416*479ab7f0SSascha Wildner		stosb				# Save char
417*479ab7f0SSascha Wildner		ret				# (Recursive)
418*479ab7f0SSascha Wildner
419*479ab7f0SSascha Wildner		.data
420*479ab7f0SSascha Wildner		.p2align 4
421*479ab7f0SSascha Wildner/*
422*479ab7f0SSascha Wildner * Global descriptor table.
423*479ab7f0SSascha Wildner */
424*479ab7f0SSascha Wildnergdt:		.word 0x0,0x0,0x0,0x0		# Null entry
425*479ab7f0SSascha Wildner		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE
426*479ab7f0SSascha Wildner		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
427*479ab7f0SSascha Wildner		.word 0xffff,0x0,0x9a00,0x0	# SEL_RCODE
428*479ab7f0SSascha Wildner		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
429*479ab7f0SSascha Wildnergdt.1:
430*479ab7f0SSascha Wildnergdtdesc:	.word gdt.1-gdt-1		# Limit
431*479ab7f0SSascha Wildner		.long gdt			# Base
432*479ab7f0SSascha Wildner/*
433*479ab7f0SSascha Wildner * Messages.
434*479ab7f0SSascha Wildner */
435*479ab7f0SSascha Wildnerm_logo: 	.asciz " \nBTX loader 1.00  "
436*479ab7f0SSascha Wildnerm_vers: 	.asciz "BTX version is \0\n"
437*479ab7f0SSascha Wildnere_fmt:		.asciz "Error: Client format not supported\n"
438*479ab7f0SSascha Wildner#ifdef BTXLDR_VERBOSE
439*479ab7f0SSascha Wildnerm_mem:		.asciz "Starting in protected mode (base mem=\0)\n"
440*479ab7f0SSascha Wildnerm_esp:		.asciz "Arguments passed (esp=\0):\n"
441*479ab7f0SSascha Wildnerm_args: 	.asciz"<howto="
442*479ab7f0SSascha Wildner		.asciz" bootdev="
443*479ab7f0SSascha Wildner		.asciz" junk="
444*479ab7f0SSascha Wildner		.asciz" "
445*479ab7f0SSascha Wildner		.asciz" "
446*479ab7f0SSascha Wildner		.asciz" bootinfo=\0>\n"
447*479ab7f0SSascha Wildnerm_rel_bi:	.asciz "Relocated bootinfo (size=48) to \0\n"
448*479ab7f0SSascha Wildnerm_rel_args:	.asciz "Relocated arguments (size=18) to \0\n"
449*479ab7f0SSascha Wildnerm_rel_btx:	.asciz "Relocated kernel (size=\0) to \0\n"
450*479ab7f0SSascha Wildnerm_base: 	.asciz "Client base address is \0\n"
451*479ab7f0SSascha Wildnerm_elf:		.asciz "Client format is ELF\n"
452*479ab7f0SSascha Wildnerm_segs: 	.asciz "text segment: offset="
453*479ab7f0SSascha Wildner		.asciz " vaddr="
454*479ab7f0SSascha Wildner		.asciz " filesz="
455*479ab7f0SSascha Wildner		.asciz " memsz=\0\n"
456*479ab7f0SSascha Wildner		.asciz "data segment: offset="
457*479ab7f0SSascha Wildner		.asciz " vaddr="
458*479ab7f0SSascha Wildner		.asciz " filesz="
459*479ab7f0SSascha Wildner		.asciz " memsz=\0\n"
460*479ab7f0SSascha Wildnerm_done: 	.asciz "Loading complete\n"
461*479ab7f0SSascha Wildner#endif
462*479ab7f0SSascha Wildner/*
463*479ab7f0SSascha Wildner * Uninitialized data area.
464*479ab7f0SSascha Wildner */
465*479ab7f0SSascha Wildnerbuf:						# Scratch buffer
466