cdboot.S revision 58713
156693Sjhb#
256693Sjhb# Copyright (c) 2000 John Baldwin
356693Sjhb# All rights reserved.
456693Sjhb#
556693Sjhb# Redistribution and use in source and binary forms are freely
656693Sjhb# permitted provided that the above copyright notice and this
756693Sjhb# paragraph and the following disclaimer are duplicated in all
856693Sjhb# such forms.
956693Sjhb#
1056693Sjhb# This software is provided "AS IS" and without any express or
1156693Sjhb# implied warranties, including, without limitation, the implied
1256693Sjhb# warranties of merchantability and fitness for a particular
1356693Sjhb# purpose.
1456693Sjhb#
1556693Sjhb
1656693Sjhb# $FreeBSD: head/sys/boot/i386/cdboot/cdboot.s 58713 2000-03-28 01:19:53Z jhb $
1756693Sjhb
1856693Sjhb#
1956693Sjhb# This simple program is a preloader for the normal boot3 loader.  It is simply
2056693Sjhb# prepended to the beginning of a fully built and btxld'd loader.  It then
2156693Sjhb# copies the loader to the address boot2 normally loads it, emulates the
2256693Sjhb# boot[12] environment (protected mode, a bootinfo struct, etc.), and then jumps
2356693Sjhb# to the start of btxldr to start the boot process.  This method allows a stock
2456693Sjhb# /boot/loader to be used w/o having to fully rewrite boot[12] to handle the
2556693Sjhb# cd9660 file system.
2656693Sjhb#
2756693Sjhb
2856693Sjhb#
2956693Sjhb# Memory locations.
3056693Sjhb#
3158713Sjhb		.set MEM_PAGE_SIZE,0x1000	# memory page size, 4k
3256693Sjhb		.set MEM_ARG,0x900		# Arguments at start
3356693Sjhb		.set MEM_ARG_BTX,0xa100		# Where we move them to so the
3456693Sjhb						#  BTX client can see them
3556693Sjhb		.set MEM_ARG_SIZE,0x18		# Size of the arguments
3656693Sjhb		.set MEM_BTX_ADDRESS,0x9000	# where BTX lives
3756693Sjhb		.set MEM_BTX_ENTRY,0x9010	# where BTX starts to execute
3858713Sjhb		.set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
3956693Sjhb		.set MEM_BTX_CLIENT,0xa000	# where BTX clients live
4056693Sjhb#
4158713Sjhb# a.out header fields
4258713Sjhb#
4358713Sjhb		.set AOUT_TEXT,0x04		# text segment size
4458713Sjhb		.set AOUT_DATA,0x08		# data segment size
4558713Sjhb		.set AOUT_BSS,0x0c		# zero'd BSS size
4658713Sjhb		.set AOUT_SYMBOLS,0x10		# symbol table
4758713Sjhb		.set AOUT_ENTRY,0x14		# entry point
4858713Sjhb		.set AOUT_HEADER,MEM_PAGE_SIZE	# size of the a.out header
4958713Sjhb#
5056693Sjhb# Flags for kargs->bootflags
5156693Sjhb#
5256693Sjhb		.set KARGS_FLAGS_CD,0x1		# flag to indicate booting from
5356693Sjhb						#  CD loader
5456693Sjhb#
5556693Sjhb# Segment selectors.
5656693Sjhb#
5756693Sjhb		.set SEL_SDATA,0x8		# Supervisor data
5856693Sjhb		.set SEL_RDATA,0x10		# Real mode data
5956693Sjhb		.set SEL_SCODE,0x18		# PM-32 code
6056693Sjhb		.set SEL_SCODE16,0x20		# PM-16 code
6156693Sjhb#
6256693Sjhb# BTX constants
6356693Sjhb#
6456693Sjhb		.set INT_SYS,0x30		# BTX syscall interrupt
6556693Sjhb#
6658713Sjhb# We expect to be loaded by the BIOS at 0x7c00 (standard boot loader entry
6758713Sjhb# point)
6856693Sjhb#
6956693Sjhb		.code16
7056693Sjhb		.globl start
7156693Sjhb		.org 0x0, 0x0
7256693Sjhb#
7356693Sjhb# BTX program loader for CD booting
7456693Sjhb#
7558713Sjhbstart:		cld				# string ops inc
7656693Sjhb		xorw %ax, %ax			# zero %ax
7756693Sjhb		movw %ax, %ss			# setup the
7858713Sjhb		movw $start, %sp		#  stack
7956693Sjhb		pushw %dx			# save the BIOS boot device in
8056693Sjhb						#  %dl for later
8158713Sjhb		movw %ax, %ds			# setup the
8258713Sjhb		movw %ax, %es			#  data segments
8358713Sjhb		movw $welcome_msg, %si		# %ds:(%si) -> welcome message
8456693Sjhb		call putstr			# display the welcome message
8556693Sjhb#
8656693Sjhb# Setup the arguments that the loader is expecting from boot[12]
8756693Sjhb#
8858713Sjhb		movw $bootinfo_msg, %si		# %ds:(%si) -> boot args message
8956693Sjhb		call putstr			# display the message
9058713Sjhb		movl $MEM_ARG, %ebx		# %ds:(%ebx) -> boot args
9156693Sjhb		movw %bx, %di			# %es:(%di) -> boot args
9256693Sjhb		xorl %eax, %eax			# zero %eax
9356693Sjhb		movw $(MEM_ARG_SIZE/4), %cx	# Size of arguments in 32-bit
9456693Sjhb						#  dwords
9556693Sjhb		rep				# Clear the arguments
9656693Sjhb		stosl				#  to zero
9756693Sjhb		popw %dx			# restore BIOS boot device
9858713Sjhb		movb %dl, 0x4(%ebx)		# set kargs->bootdev
9958713Sjhb		orb $KARGS_FLAGS_CD, 0x8(%ebx)	# kargs->bootflags |=
10058713Sjhb						#  KARGS_FLAGS_CD
10156693Sjhb#
10256693Sjhb# Turn on the A20 address line
10356693Sjhb#
10456693Sjhb		call seta20			# Turn A20 on
10556693Sjhb#
10656693Sjhb# Relocate the loader and BTX using a very lazy protected mode
10756693Sjhb#
10856693Sjhb		movw $relocate_msg, %si		# Display the
10956693Sjhb		call putstr			#  relocation message
11058713Sjhb		movl end+AOUT_ENTRY, %edi	# %edi is the destination
11158713Sjhb		movl $(end+AOUT_HEADER), %esi	# %esi is
11258713Sjhb						#  the start of the text
11358713Sjhb						#  segment
11458713Sjhb		movl end+AOUT_TEXT, %ecx	# %ecx = length of the text
11558713Sjhb						#  segment
11656693Sjhb		lgdt gdtdesc			# setup our own gdt
11756693Sjhb		cli				# turn off interrupts
11856693Sjhb		movl %cr0, %eax			# Turn on
11958713Sjhb		orb $0x1, %al			#  protected
12056693Sjhb		movl %eax, %cr0			#  mode
12156693Sjhb		.byte 0xea			# long jump to
12258713Sjhb		.word pm_start			#   clear the instruction
12358713Sjhb		.word SEL_SCODE			#   pre-fetch queue
12456693Sjhb		.code32
12556693Sjhbpm_start:	movw $SEL_SDATA, %ax		# Initialize
12656693Sjhb		movw %ax, %ds			#  %ds and
12756693Sjhb		movw %ax, %es			#  %es to a flat selector
12858713Sjhb		rep				# Relocate the
12958713Sjhb		movsb				#  text segment
13058713Sjhb		addl $(MEM_PAGE_SIZE - 1), %edi	# pad %edi out to a new page
13158713Sjhb		andl $~(MEM_PAGE_SIZE - 1), %edi #  for the data segment
13258713Sjhb		movl end+AOUT_DATA, %ecx	# size of the data segment
13358713Sjhb		rep				# Relocate the
13458713Sjhb		movsb				#  data segment
13558713Sjhb		movl end+AOUT_BSS, %ecx		# size of the bss
13658713Sjhb		xorl %eax, %eax			# zero %eax
13758713Sjhb		addb $3, %cl			# round %ecx up to
13858713Sjhb		shrl $2, %ecx			#  a multiple of 4
13958713Sjhb		rep				# zero the
14058713Sjhb		stosl				#  bss
14158713Sjhb		movl end+AOUT_ENTRY, %esi	# %esi -> relocated loader
14258713Sjhb		addl $MEM_BTX_OFFSET, %esi	# %esi -> BTX in the loader
14356693Sjhb		movl $MEM_BTX_ADDRESS, %edi	# %edi -> where BTX needs to go
14456693Sjhb		movzwl 0xa(%esi), %ecx		# %ecx -> length of BTX
14556693Sjhb		rep				# Relocate
14656693Sjhb		movsb				#  BTX
14758713Sjhb		ljmp $SEL_SCODE16,$pm_16	# Jump to 16-bit PM
14856693Sjhb		.code16
14956693Sjhbpm_16:		movw $SEL_RDATA, %ax		# Initialize
15056693Sjhb		movw %ax, %ds			#  %ds and
15156693Sjhb		movw %ax, %es			#  %es to a real mode selector
15256693Sjhb		movl %cr0, %eax			# Turn off
15358713Sjhb		andb $~0x1, %al			#  protected
15456693Sjhb		movl %eax, %cr0			#  mode
15556693Sjhb		.byte 0xea			# Long jump to
15656693Sjhb		.word pm_end			#   clear the instruction
15758713Sjhb		.word 0x0			#   pre-fetch
15856693Sjhbpm_end:		sti				# Turn interrupts back on now
15956693Sjhb#
16056693Sjhb# Copy the BTX client to MEM_BTX_CLIENT
16156693Sjhb#
16258713Sjhb		xorw %ax, %ax			# zero %ax and set
16358713Sjhb		movw %ax, %ds			#  %ds and %es
16458713Sjhb		movw %ax, %es			#  to segment 0
16556693Sjhb		movw $MEM_BTX_CLIENT, %di	# Prepare to relocate
16656693Sjhb		movw $btx_client, %si		#  the simple btx client
16756693Sjhb		movw $(btx_client_end-btx_client), %cx # length of btx client
16856693Sjhb		rep				# Relocate the
16956693Sjhb		movsb				#  simple BTX client
17056693Sjhb#
17156693Sjhb# Copy the boot[12] args to where the BTX client can see them
17256693Sjhb#
17356693Sjhb		movw $MEM_ARG, %si		# where the args are at now
17456693Sjhb		movw $MEM_ARG_BTX, %di		# where the args are moving to
17556693Sjhb		movw $(MEM_ARG_SIZE/4), %cx	# size of the arguments in longs
17656693Sjhb		rep				# Relocate
17756693Sjhb		movsl				#  the words
17856693Sjhb#
17958713Sjhb# Save the entry point so the client can get to it later on
18058713Sjhb#
18158713Sjhb		movl end+AOUT_ENTRY, %eax	# load the entry point
18258713Sjhb		stosl				# add it to the end of the
18358713Sjhb						#  arguments
18458713Sjhb#
18556693Sjhb# Now we just start up BTX and let it do the rest
18656693Sjhb#
18758713Sjhb		movw $jump_message, %si		# Display the
18856693Sjhb		call putstr			#  jump message
18956693Sjhb		.byte 0xea			# Jump to
19056693Sjhb		.word MEM_BTX_ENTRY 		# BTX entry
19156693Sjhb		.word 0x0			#  point
19256693Sjhb
19356693Sjhb#
19456693Sjhb# Display a null-terminated string
19556693Sjhb#
19656693Sjhbputstr:		lodsb				# load %al from %ds:(%si)
19756693Sjhb		testb %al,%al			# stop at null
19856693Sjhb		jnz putc			# if the char != null, output it
19956693Sjhb		ret				# return when null is hit
20056693Sjhbputc:		movw $0x7,%bx			# attribute for output
20156693Sjhb		movb $0xe,%ah			# BIOS: put_char
20256693Sjhb		int $0x10			# call BIOS, print char in %al
20356693Sjhb		jmp putstr			# keep looping
20456693Sjhb
20556693Sjhb#
20656693Sjhb# Enable A20
20756693Sjhb#
20856693Sjhbseta20: 	cli				# Disable interrupts
20956693Sjhbseta20.1:	inb $0x64,%al			# Get status
21056693Sjhb		testb $0x2,%al			# Busy?
21156693Sjhb		jnz seta20.1			# Yes
21256693Sjhb		movb $0xd1,%al			# Command: Write
21356693Sjhb		outb %al,$0x64			#  output port
21456693Sjhbseta20.2:	inb $0x64,%al			# Get status
21556693Sjhb		testb $0x2,%al			# Busy?
21656693Sjhb		jnz seta20.2			# Yes
21756693Sjhb		movb $0xdf,%al			# Enable
21856693Sjhb		outb %al,$0x60			#  A20
21956693Sjhb		sti				# Enable interrupts
22056693Sjhb		ret				# To caller
22156693Sjhb
22256693Sjhb#
22358713Sjhb# BTX client to start btxldr
22456693Sjhb#
22556693Sjhb		.code32
22656693Sjhbbtx_client:	movl $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
22756693Sjhb						# %ds:(%esi) -> end
22856693Sjhb						#  of boot[12] args
22956693Sjhb		movl $(MEM_ARG_SIZE/4), %ecx	# Number of words to push
23056693Sjhb		std				# Go backwards
23156693Sjhbpush_arg:	lodsl				# Read argument
23256693Sjhb		pushl %eax			# Push it onto the stack
23356693Sjhb		loop push_arg			# Push all of the arguments
23456693Sjhb		cld				# In case anyone depends on this
23558713Sjhb		pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
23658713Sjhb						#  the loader
23756693Sjhb		pushl %eax			# Emulate a near call
23856693Sjhb		movl $0x1, %eax			# 'exec' system call
23956693Sjhb		int $INT_SYS			# BTX system call
24056693Sjhbbtx_client_end:
24156693Sjhb		.code16
24256693Sjhb
24356693Sjhb		.p2align 4
24456693Sjhb#
24556693Sjhb# Global descriptor table.
24656693Sjhb#
24756693Sjhbgdt:		.word 0x0,0x0,0x0,0x0		# Null entry
24856693Sjhb		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
24956693Sjhb		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
25056693Sjhb		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE (32-bit)
25156693Sjhb		.word 0xffff,0x0,0x9a00,0x8f	# SEL_SCODE16 (16-bit)
25256693Sjhbgdt.1:
25356693Sjhb#
25456693Sjhb# Pseudo-descriptors.
25556693Sjhb#
25656693Sjhbgdtdesc:	.word gdt.1-gdt-1		# Limit
25758713Sjhb		.long gdt			# Base
25856693Sjhb
25956693Sjhbwelcome_msg:	.asciz	"CD Loader 1.00\r\n\n"
26056693Sjhbbootinfo_msg:	.asciz	"Building the boot loader arguments\r\n"
26156693Sjhbrelocate_msg:	.asciz	"Relocating the loader and the BTX\r\n"
26256693Sjhbjump_message:	.asciz	"Starting the BTX loader\r\n"
26356693Sjhb
26456693Sjhbend:
265