btxldr.S revision 125780
143561Skato#
243561Skato# Copyright (c) 1998 Robert Nordier
343561Skato# All rights reserved.
443561Skato#
543561Skato# Redistribution and use in source and binary forms are freely
643561Skato# permitted provided that the above copyright notice and this
743561Skato# paragraph and the following disclaimer are duplicated in all
843561Skato# such forms.
943561Skato#
1043561Skato# This software is provided "AS IS" and without any express or
1143561Skato# implied warranties, including, without limitation, the implied
1243561Skato# warranties of merchantability and fitness for a particular
1343561Skato# purpose.
1443561Skato#
1543561Skato
1650477Speter# $FreeBSD: head/sys/boot/pc98/btx/btxldr/btxldr.S 125780 2004-02-13 15:39:59Z nyan $
1743561Skato
1843561Skato#
1943561Skato# Prototype BTX loader program, written in a couple of hours.  The
2043561Skato# real thing should probably be more flexible, and in C.
2143561Skato#
2243561Skato
2343561Skato#
2443561Skato# Memory locations.
2543561Skato#
2643561Skato		.set MEM_STUB,0x600		# Real mode stub
2743561Skato		.set MEM_ESP,0x1000		# New stack pointer
2843561Skato		.set MEM_TBL,0x5000		# BTX page tables
2943561Skato		.set MEM_ENTRY,0x9010		# BTX entry point
3058871Skato		.set MEM_DATA,start+0x1000	# Data segment
3143561Skato#
3243561Skato# Segment selectors.
3343561Skato#
3443561Skato		.set SEL_SCODE,0x8		# 4GB code
3543561Skato		.set SEL_SDATA,0x10		# 4GB data
3643561Skato		.set SEL_RCODE,0x18		# 64K code
3743561Skato		.set SEL_RDATA,0x20		# 64K data
3843561Skato#
3943561Skato# Paging constants.
4043561Skato#
4143561Skato		.set PAG_SIZ,0x1000		# Page size
4243561Skato		.set PAG_ENT,0x4		# Page entry size
4343561Skato#
4443561Skato# Screen constants.
4543561Skato#
46125780Snyan#ifdef PC98
4743561Skato		.set SCR_MAT,0xe1		# Mode/attribute
48125780Snyan#else
4943561Skato		.set SCR_MAT,0x7		# Mode/attribute
50125780Snyan#endif
5143561Skato		.set SCR_COL,0x50		# Columns per row
5243561Skato		.set SCR_ROW,0x19		# Rows per screen
5343561Skato#
5443561Skato# BIOS Data Area locations.
5543561Skato#
56125780Snyan#ifdef PC98
5743561Skato		.set BDA_MEM,0xa1501		# Free memory
5843561Skato		.set BDA_POS,0xa153e		# Cursor position
59125780Snyan#else
6043561Skato		.set BDA_MEM,0x413		# Free memory
6143561Skato		.set BDA_SCR,0x449		# Video mode
6243561Skato		.set BDA_POS,0x450		# Cursor position
63125780Snyan#endif
6443561Skato#
6543561Skato# Required by aout gas inadequacy.
6643561Skato#
6743561Skato		.set SIZ_STUB,0x1a		# Size of stub
6843561Skato#
6958871Skato# We expect to be loaded by boot2 at the origin defined in ./Makefile.
7043561Skato#
7143561Skato		.globl start
7243561Skato#
7343561Skato# BTX program loader for ELF clients.
7443561Skato#
7543561Skatostart:		cld				# String ops inc
76125780Snyan#ifdef PC98
7743561Skato		cli
7843561Skatogdcwait.1:	inb $0x60,%al
7943561Skato		testb $0x04,%al
8043561Skato		jz gdcwait.1
8143561Skato		movb $0xe0,%al
8243561Skato		outb %al,$0x62
8343561Skato		nop
8443561Skatogdcwait.2:	inb $0x60,%al
8543561Skato		testb $0x01,%al
8643561Skato		jz gdcwait.2
8743561Skato		inb $0x62,%al
8843561Skato		movb %al,%dl
8943561Skato		inb $0x62,%al
9043561Skato		movb %al,%dh
9143561Skato		inb $0x62,%al
9243561Skato		inb $0x62,%al
9343561Skato		inb $0x62,%al
9443561Skato		shlw $1,%dx
9543561Skato		movl $BDA_POS,%ebx
9643561Skato		movw %dx,(%ebx)
97125780Snyan#endif
9843561Skato		movl $m_logo,%esi		# Identify
9943561Skato		call putstr			#  ourselves
10043561Skato		movzwl BDA_MEM,%eax		# Get base memory
101125780Snyan#ifdef PC98
10243561Skato		andl $0x7,%eax
10343561Skato		incl %eax
10443561Skato		shll $0x11,%eax			#  in bytes
105125780Snyan#else
10643561Skato		shll $0xa,%eax			#  in bytes
107125780Snyan#endif
10843561Skato		movl %eax,%ebp			# Base of user stack
109125780Snyan#ifdef BTXLDR_VERBOSE
11043561Skato		movl $m_mem,%esi		# Display
11158871Skato		call hexout			#  amount of
11258871Skato		call putstr			#  base memory
113125780Snyan#endif
11443561Skato		lgdt gdtdesc			# Load new GDT
11543561Skato#
11643561Skato# Relocate caller's arguments.
11743561Skato#
118125780Snyan#ifdef BTXLDR_VERBOSE
11943561Skato		movl $m_esp,%esi		# Display
12058871Skato		movl %esp,%eax			#  caller
12158871Skato		call hexout			#  stack
12258871Skato		call putstr			#  pointer
12343561Skato		movl $m_args,%esi		# Format string
12443561Skato		leal 0x4(%esp,1),%ebx		# First argument
12543561Skato		movl $0x6,%ecx			# Count
12643561Skatostart.1:	movl (%ebx),%eax		# Get argument and
12743561Skato		addl $0x4,%ebx			#  bump pointer
12858871Skato		call hexout			# Display it
12943561Skato		loop start.1			# Till done
13058871Skato		call putstr			# End message
131125780Snyan#endif
13243561Skato		movl $0x48,%ecx 		# Allocate space
13343561Skato		subl %ecx,%ebp			#  for bootinfo
13458871Skato		movl 0x18(%esp,1),%esi		# Source: bootinfo
13558871Skato		cmpl $0x0, %esi			# If the bootinfo pointer
13658871Skato		je start_null_bi		#  is null, don't copy it
13743561Skato		movl %ebp,%edi			# Destination
13843561Skato		rep				# Copy
13943561Skato		movsb				#  it
14043561Skato		movl %ebp,0x18(%esp,1)		# Update pointer
141125780Snyan#ifdef BTXLDR_VERBOSE
14243561Skato		movl $m_rel_bi,%esi		# Display
14343561Skato		movl %ebp,%eax			#  bootinfo
14458871Skato		call hexout			#  relocation
14558871Skato		call putstr			#  message
146125780Snyan#endif
14758871Skatostart_null_bi:	movl $0x18,%ecx 		# Allocate space
14843561Skato		subl %ecx,%ebp			#  for arguments
14943561Skato		leal 0x4(%esp,1),%esi		# Source
15043561Skato		movl %ebp,%edi			# Destination
15143561Skato		rep				# Copy
15243561Skato		movsb				#  them
153125780Snyan#ifdef BTXLDR_VERBOSE
15443561Skato		movl $m_rel_args,%esi		# Display
15543561Skato		movl %ebp,%eax			#  argument
15658871Skato		call hexout			#  relocation
15758871Skato		call putstr			#  message
158125780Snyan#endif
15943561Skato#
16043561Skato# Set up BTX kernel.
16143561Skato#
16243561Skato		movl $MEM_ESP,%esp		# Set up new stack
16343561Skato		movl $MEM_DATA,%ebx		# Data segment
16443561Skato		movl $m_vers,%esi		# Display BTX
16543561Skato		call putstr			#  version message
16643561Skato		movb 0x5(%ebx),%al		# Get major version
16743561Skato		addb $'0',%al			# Display
16843561Skato		call putchr			#  it
16943561Skato		movb $'.',%al			# And a
17043561Skato		call putchr			#  dot
17143561Skato		movb 0x6(%ebx),%al		# Get minor
17243561Skato		xorb %ah,%ah			#  version
17343561Skato		movb $0xa,%dl			# Divide
17443561Skato		divb %dl,%al			#  by 10
17543561Skato		addb $'0',%al			# Display
17643561Skato		call putchr			#  tens
17743561Skato		movb %ah,%al			# Get units
17843561Skato		addb $'0',%al			# Display
17943561Skato		call putchr			#  units
18043561Skato		call putstr			# End message
18143561Skato		movl %ebx,%esi			# BTX image
18243561Skato		movzwl 0x8(%ebx),%edi		# Compute
18343561Skato		orl $PAG_SIZ/PAG_ENT-1,%edi	#  the
18443561Skato		incl %edi			#  BTX
18543561Skato		shll $0x2,%edi			#  load
18643561Skato		addl $MEM_TBL,%edi		#  address
18758871Skato		pushl %edi			# Save load address
18843561Skato		movzwl 0xa(%ebx),%ecx		# Image size
189125780Snyan#ifdef BTXLDR_VERBOSE
19058871Skato		pushl %ecx			# Save image size
191125780Snyan#endif
19243561Skato		rep				# Relocate
19343561Skato		movsb				#  BTX
19443561Skato		movl %esi,%ebx			# Keep place
195125780Snyan#ifdef BTXLDR_VERBOSE
19643561Skato		movl $m_rel_btx,%esi		# Restore
19743561Skato		popl %eax			#  parameters
19858871Skato		call hexout			#  and
199125780Snyan#endif
20043561Skato		popl %ebp			#  display
201125780Snyan#ifdef BTXLDR_VERBOSE
20243561Skato		movl %ebp,%eax			#  the
20358871Skato		call hexout			#  relocation
20458871Skato		call putstr			#  message
205125780Snyan#endif
20643561Skato		addl $PAG_SIZ,%ebp		# Display
207125780Snyan#ifdef BTXLDR_VERBOSE
20843561Skato		movl $m_base,%esi		#  the
20943561Skato		movl %ebp,%eax			#  user
21058871Skato		call hexout			#  base
21158871Skato		call putstr			#  address
212125780Snyan#endif
21343561Skato#
21443561Skato# Set up ELF-format client program.
21543561Skato#
21643561Skato		cmpl $0x464c457f,(%ebx) 	# ELF magic number?
21743561Skato		je start.3			# Yes
21843561Skato		movl $e_fmt,%esi		# Display error
21943561Skato		call putstr			#  message
22043561Skatostart.2:	jmp start.2			# Hang
22158871Skatostart.3:
222125780Snyan#ifdef BTXLDR_VERBOSE
22358871Skato		movl $m_elf,%esi		# Display ELF
22458871Skato		call putstr			#  message
22543561Skato		movl $m_segs,%esi		# Format string
226125780Snyan#endif
22743561Skato		movl $0x2,%edi			# Segment count
22843561Skato		movl 0x1c(%ebx),%edx		# Get e_phoff
22943561Skato		addl %ebx,%edx			# To pointer
23043561Skato		movzwl 0x2c(%ebx),%ecx		# Get e_phnum
23143561Skatostart.4:	cmpl $0x1,(%edx)		# Is p_type PT_LOAD?
23243561Skato		jne start.6			# No
233125780Snyan#ifdef BTXLDR_VERBOSE
23443561Skato		movl 0x4(%edx),%eax		# Display
23558871Skato		call hexout			#  p_offset
23643561Skato		movl 0x8(%edx),%eax		# Display
23758871Skato		call hexout			#  p_vaddr
23843561Skato		movl 0x10(%edx),%eax		# Display
23958871Skato		call hexout			#  p_filesz
24043561Skato		movl 0x14(%edx),%eax		# Display
24158871Skato		call hexout			#  p_memsz
24258871Skato		call putstr			# End message
243125780Snyan#endif
24443561Skato		pushl %esi			# Save
24543561Skato		pushl %edi			#  working
24643561Skato		pushl %ecx			#  registers
24743561Skato		movl 0x4(%edx),%esi		# Get p_offset
24843561Skato		addl %ebx,%esi			#  as pointer
24943561Skato		movl 0x8(%edx),%edi		# Get p_vaddr
25043561Skato		addl %ebp,%edi			#  as pointer
25143561Skato		movl 0x10(%edx),%ecx		# Get p_filesz
25243561Skato		rep				# Set up
25343561Skato		movsb				#  segment
25443561Skato		movl 0x14(%edx),%ecx		# Any bytes
25543561Skato		subl 0x10(%edx),%ecx		#  to zero?
25643561Skato		jz start.5			# No
25743561Skato		xorb %al,%al			# Then
25843561Skato		rep				#  zero
25943561Skato		stosb				#  them
26043561Skatostart.5:	popl %ecx			# Restore
26143561Skato		popl %edi			#  working
26243561Skato		popl %esi			#  registers
26343561Skato		decl %edi			# Segments to do
26443561Skato		je start.7			# If none
26543561Skatostart.6:	addl $0x20,%edx 		# To next entry
26643561Skato		loop start.4			# Till done
26758871Skatostart.7:
268125780Snyan#ifdef BTXLDR_VERBOSE
26958871Skato		movl $m_done,%esi		# Display done
27058871Skato		call putstr			#  message
271125780Snyan#endif
27243561Skato		movl $start.8,%esi		# Real mode stub
27343561Skato		movl $MEM_STUB,%edi		# Destination
27461064Snyan		movl $start.9-start.8,%ecx	# Size
27543561Skato		rep				# Relocate
27643561Skato		movsb				#  it
27743561Skato		ljmp $SEL_RCODE,$MEM_STUB	# To 16-bit code
27861064Snyan		.code16
27961064Snyanstart.8:	xorw %ax,%ax			# Data
28043561Skato		movb $SEL_RDATA,%al		#  selector
28161064Snyan		movw %ax,%ss			# Reload SS
28261064Snyan		movw %ax,%ds			# Reset
28361064Snyan		movw %ax,%es			#  other
28461064Snyan		movw %ax,%fs			#  segment
28561064Snyan		movw %ax,%gs			#  limits
28643561Skato		movl %cr0,%eax			# Switch to
28761064Snyan		decw %ax			#  real
28843561Skato		movl %eax,%cr0			#  mode
28961064Snyan		ljmp $0,$MEM_ENTRY		# Jump to BTX entry point
29043561Skatostart.9:
29161064Snyan		.code32
29243561Skato#
29343561Skato# Output message [ESI] followed by EAX in hex.
29443561Skato#
29543561Skatohexout: 	pushl %eax			# Save
29643561Skato		call putstr			# Display message
29743561Skato		popl %eax			# Restore
29843561Skato		pushl %esi			# Save
29943561Skato		pushl %edi			#  caller's
30043561Skato		movl $buf,%edi			# Buffer
30143561Skato		pushl %edi			# Save
30243561Skato		call hex32			# To hex
30343561Skato		xorb %al,%al			# Terminate
30443561Skato		stosb				#  string
30543561Skato		popl %esi			# Restore
30643561Skatohexout.1:	lodsb				# Get a char
30743561Skato		cmpb $'0',%al			# Leading zero?
30843561Skato		je hexout.1			# Yes
30943561Skato		testb %al,%al			# End of string?
31043561Skato		jne hexout.2			# No
31143561Skato		decl %esi			# Undo
31243561Skatohexout.2:	decl %esi			# Adjust for inc
31343561Skato		call putstr			# Display hex
31443561Skato		popl %edi			# Restore
31543561Skato		popl %esi			#  caller's
31643561Skato		ret				# To caller
31743561Skato#
31843561Skato# Output zero-terminated string [ESI] to the console.
31943561Skato#
32043561Skatoputstr.0:	call putchr			# Output char
32143561Skatoputstr: 	lodsb				# Load char
32243561Skato		testb %al,%al			# End of string?
32343561Skato		jne putstr.0			# No
32443561Skato		ret				# To caller
32543561Skato#
32643561Skato# Output character AL to the console.
32743561Skato#
32843561Skatoputchr: 	pusha				# Save
32943561Skato		xorl %ecx,%ecx			# Zero for loops
33043561Skato		movb $SCR_MAT,%ah		# Mode/attribute
33143561Skato		movl $BDA_POS,%ebx		# BDA pointer
33243561Skato		movw (%ebx),%dx 		# Cursor position
333125780Snyan#ifdef PC98
33443561Skato		movl $0xa0000,%edi		# Regen buffer (color)
335125780Snyan#else
33643561Skato		movl $0xb8000,%edi		# Regen buffer (color)
33743561Skato		cmpb %ah,BDA_SCR-BDA_POS(%ebx)	# Mono mode?
33843561Skato		jne putchr.1			# No
33943561Skato		xorw %di,%di			# Regen buffer (mono)
340125780Snyan#endif
34143561Skatoputchr.1:	cmpb $0xa,%al			# New line?
34243561Skato		je putchr.2			# Yes
343125780Snyan#ifdef PC98
34443561Skato		movw %dx,%cx
34543561Skato		movb %al,(%edi,%ecx,1)		# Write char
34643561Skato		addl $0x2000,%ecx
34743561Skato		movb %ah,(%edi,%ecx,1)		# Write attr
34843561Skato		addw $0x2,%dx
34943561Skato		jmp putchr.3
35043561Skatoputchr.2:	movw %dx,%ax
35143561Skato		movb $SCR_COL*2,%dl
35243561Skato		div %dl
35343561Skato		incb %al
35443561Skato		mul %dl
35543561Skato		movw %ax,%dx
35643561Skatoputchr.3:	cmpw $SCR_COL*SCR_ROW*2,%dx
357125780Snyan#else
35843561Skato		xchgl %eax,%ecx 		# Save char
35943561Skato		movb $SCR_COL,%al		# Columns per row
36043561Skato		mulb %dh			#  * row position
36143561Skato		addb %dl,%al			#  + column
36243561Skato		adcb $0x0,%ah			#  position
36343561Skato		shll %eax			#  * 2
36443561Skato		xchgl %eax,%ecx 		# Swap char, offset
36543561Skato		movw %ax,(%edi,%ecx,1)		# Write attr:char
36643561Skato		incl %edx			# Bump cursor
36743561Skato		cmpb $SCR_COL,%dl		# Beyond row?
36843561Skato		jb putchr.3			# No
36943561Skatoputchr.2:	xorb %dl,%dl			# Zero column
37043561Skato		incb %dh			# Bump row
37143561Skatoputchr.3:	cmpb $SCR_ROW,%dh		# Beyond screen?
372125780Snyan#endif
37343561Skato		jb putchr.4			# No
37443561Skato		leal 2*SCR_COL(%edi),%esi	# New top line
37543561Skato		movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
37643561Skato		rep				# Scroll
37743561Skato		movsl				#  screen
37843561Skato		movb $' ',%al			# Space
379125780Snyan#ifdef PC98
38043561Skato		xorb %ah,%ah
381125780Snyan#endif
38243561Skato		movb $SCR_COL,%cl		# Columns to clear
38343561Skato		rep				# Clear
38443561Skato		stosw				#  line
385125780Snyan#ifdef PC98
38643561Skato		movw $(SCR_ROW-1)*SCR_COL*2,%dx
38743561Skatoputchr.4:	movw %dx,(%ebx) 		# Update position
38843561Skato		shrw $1,%dx
38943561Skatogdcwait.3:	inb $0x60,%al
39043561Skato		testb $0x04,%al
39143561Skato		jz gdcwait.3
39243561Skato		movb $0x49,%al
39343561Skato		outb %al,$0x62
39443561Skato		movb %dl,%al
39543561Skato		outb %al,$0x60
39643561Skato		movb %dh,%al
39743561Skato		outb %al,$0x60
398125780Snyan#else
39943561Skato		movb $SCR_ROW-1,%dh		# Bottom line
40043561Skatoputchr.4:	movw %dx,(%ebx) 		# Update position
401125780Snyan#endif
40243561Skato		popa				# Restore
40343561Skato		ret				# To caller
40443561Skato#
40543561Skato# Convert EAX, AX, or AL to hex, saving the result to [EDI].
40643561Skato#
40743561Skatohex32:		pushl %eax			# Save
40843561Skato		shrl $0x10,%eax 		# Do upper
40943561Skato		call hex16			#  16
41043561Skato		popl %eax			# Restore
41143561Skatohex16:		call hex16.1			# Do upper 8
41243561Skatohex16.1:	xchgb %ah,%al			# Save/restore
41343561Skatohex8:		pushl %eax			# Save
41443561Skato		shrb $0x4,%al			# Do upper
41543561Skato		call hex8.1			#  4
41643561Skato		popl %eax			# Restore
41743561Skatohex8.1: 	andb $0xf,%al			# Get lower 4
41843561Skato		cmpb $0xa,%al			# Convert
41943561Skato		sbbb $0x69,%al			#  to hex
42043561Skato		das				#  digit
42143561Skato		orb $0x20,%al			# To lower case
42243561Skato		stosb				# Save char
42343561Skato		ret				# (Recursive)
42443561Skato
42543561Skato		.data
42643561Skato		.p2align 4
42743561Skato#
42843561Skato# Global descriptor table.
42943561Skato#
43043561Skatogdt:		.word 0x0,0x0,0x0,0x0		# Null entry
43143561Skato		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE
43243561Skato		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
43343561Skato		.word 0xffff,0x0,0x9a00,0x0	# SEL_RCODE
43443561Skato		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
43543561Skatogdt.1:
43643561Skatogdtdesc:	.word gdt.1-gdt-1		# Limit
43743561Skato		.long gdt			# Base
43843561Skato#
43943561Skato# Messages.
44043561Skato#
44152148Sbrianm_logo: 	.asciz " \nBTX loader 1.00  "
44243561Skatom_vers: 	.asciz "BTX version is \0\n"
44343561Skatoe_fmt:		.asciz "Error: Client format not supported\n"
444125780Snyan#ifdef BTXLDR_VERBOSE
44543561Skatom_mem:		.asciz "Starting in protected mode (base mem=\0)\n"
44643561Skatom_esp:		.asciz "Arguments passed (esp=\0):\n"
44743561Skatom_args: 	.asciz"<howto="
44843561Skato		.asciz" bootdev="
44943561Skato		.asciz" junk="
45043561Skato		.asciz" "
45143561Skato		.asciz" "
45243561Skato		.asciz" bootinfo=\0>\n"
45343561Skatom_rel_bi:	.asciz "Relocated bootinfo (size=48) to \0\n"
45443561Skatom_rel_args:	.asciz "Relocated arguments (size=18) to \0\n"
45543561Skatom_rel_btx:	.asciz "Relocated kernel (size=\0) to \0\n"
45643561Skatom_base: 	.asciz "Client base address is \0\n"
45743561Skatom_elf:		.asciz "Client format is ELF\n"
45843561Skatom_segs: 	.asciz "text segment: offset="
45943561Skato		.asciz " vaddr="
46043561Skato		.asciz " filesz="
46143561Skato		.asciz " memsz=\0\n"
46243561Skato		.asciz "data segment: offset="
46343561Skato		.asciz " vaddr="
46443561Skato		.asciz " filesz="
46543561Skato		.asciz " memsz=\0\n"
46643561Skatom_done: 	.asciz "Loading complete\n"
467125780Snyan#endif
46843561Skato#
46943561Skato# Uninitialized data area.
47043561Skato#
47143561Skatobuf:						# Scratch buffer
472